Tips for accurately defining prop types in next.js when utilizing typescript?

Here is the content of my index.tsx file:

    import type { NextPage } from "next";
    
    type AppProps = {
      articles: {
        userId: number;
        id: number;
        title: string;
        body: string;
      };
    };
    
    const Home: NextPage = ({articles}:AppProps) => {
      return (
        <div>
          <h1>Welcome to {articles.title}</h1>
        </div>
      );
    };

    export const getStaticProps = async () => {
    const res = await fetch('https://jsonplaceholder.typicode.com/posts/1')
    const articles = await res.json();
    
      return {
        props: { articles },
      };
    };
 export default Home;

Although the code renders, I encountered an error in my Home component. The error message displayed is as follows:

Type '({ articles }: AppProps) => JSX.Element' is not assignable to type 'NextPage<{}, {}>'.
  Type '({ articles }: AppProps) => JSX.Element' is not assignable to type 'FunctionComponent<{}> & { getInitialProps?(context: NextPageContext): {} | Promise<{}>; }'.
    Type '({ articles }: AppProps) => JSX.Element' is not assignable to type 'FunctionComponent<{}>'.
      Types of parameters '__0' and 'props' are incompatible.
        Property 'articles' is missing in type '{}' but required in type 'AppProps'.

I am unsure what I might be doing incorrectly. Any assistance would be greatly appreciated.

Answer №1

NextPage is built upon NextComponentType, which includes default values for initial page data (props) in a type parameter list:

// When no type arguments are passed, `props` defaults to type `{}`
const Home: NextPage = () => { /*...*/ }

When providing props to a NextPage component, you must also specify your type as an argument.

An error will occur in TypeScript if articles is used on type {}:

// The `AppProps` annotation assigns types to the function argument itself,
// but without type arguments in `NextPage`, `props` remains type `{}`
const Home: NextPage = ({ articles }: AppProps) => { /*...*/ }

To inform NextPage about the type of props, include AppProps as a type argument like this:

// Type annotation can be omitted from the function argument since `AppProps`
// will be inferred
const Home: NextPage<AppProps> = ({ articles }) => { /*...*/ }

Answer №2

You may utilize either InferGetStaticPropsType or InferGetServerSidePropsType based on your requirements.

Here's an illustration:

    import type { InferGetStaticPropsType } from "next";
    
    type Post = {
      userId: number;
      id: number;
      title: string;
      body: string;
    };
    
    const HomePage = ({posts}: InferGetStaticPropsType<typeof getStaticProps>) => {
      return (
        <section>
          <h1>Greetings! {posts.title}</h1>
        </section>
      );
    };

    export const getStaticProps = async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts/1')
    const posts: Post[] = await response.json();
    
      return {
        props: { posts },
      };
    };
 export default HomePage;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Uploading Files with Typescript Promises

Hello everyone, I'm facing an issue where a dialog window is opening before all the files are uploaded to the server. Can anyone please guide me on what might be going wrong in my code? public UploadAll() { this.doAsyncTask().then(() => ...

Error encountered: Imagemagick throwing a typeerror due to the inability to parse properties of undefined while trying to read 'convert

I'm currently working on developing a pdf conversion feature for my nestjs project. Unfortunately, I've encountered an error that reads as follows: TypeError: Cannot read properties of undefined (reading 'convert') I am pretty confiden ...

What is the purpose of the .default() method being added to the class constructor in transpiled Typescript code

In TypeScript, I have the following code snippet to create an instance of ConnectRoles Middleware in Express: let user = new ConnectRoles(config); The middleware initialization is expected to be a simple call to a constructor. However, after transpiling, ...

TypeB should utilize InterfaceA for best practice

I have the following TypeScript code snippet. interface InterfaceA { id: string; key: string; value: string | number; } type TypeB = null; const sample: TypeB = { id: '1' }; I am looking for simple and maintainable solutions where TypeB ...

Using Promise<void> instead of Promise<any> is the preferred approach

Working with AngularJS, I have created several asynchronous functions that all use the same signature, which is app.Domain.GenericModel.EntityBase (my generic model). Here is an example: get(resource: string): ng.IPromise<app.Domain.GenericModel.Entity ...

The successful operation of 'Ionic serve --lab' may involve the need to manually save the app.module

We are currently working on an Ionic project that consists of several pages and a single custom provider named request.ts. The issue we are facing is that whenever we launch it using the command ionic serve --lab, the compilation fails (with the error poin ...

Is there a way to set the submitted variable to true when the form group is submitted, then revert it to false when the user makes changes to the form?

With just one FormGroup, I ensure that when a user submits the form with errors the 'submitted' variable is set to true, displaying the errors. However, my challenge now is how to reset this variable to false when the user makes any changes after ...

Unable to assign user roles in next-auth due to the absence of matching modifiers for user

I am currently working on implementing user roles in next-auth. Within my database, I have defined a prisma enum UserRole with the values 'ADMIN' and 'USER'. In my auth.ts file, I included the role property in the session object and enc ...

What could be the reason for receiving the error "client.getVersion is not a function" while using Braintree (Braintree-Web)?

When attempting to render the hostedFields from Braintree, I encounter an issue. After creating a key and obtaining my token, I pass it to my function to create the hostedFields. However, I am faced with an error message stating client.getVersion is not ...

Is it better to define a function within useEffect or externally?

What is the reason behind defining the fetchData function inside the useEffect instead of outside? Link: https://github.com/zeit/next.js/blob/canary/examples/with-graphql-faunadb/lib/useFetch.js import { useState, useEffect } from 'react' exp ...

How can I upload multiple images in one request using Typescript?

HTML: <div> <input type ="file" (change)="selectFiles($event)" multiple="multiple" /> </div> Function to handle the change event selectFiles(event) { const reader = new FileReader(); if (event.target.files & ...

Guide on how to update an array within typed angular reactive forms

I'm currently working on finding a solution for patching a form array in a strongly-typed reactive Angular form. I've noticed that patchValue and setValue don't consistently work as expected with FormControl. Here's an example of the fo ...

Why do optional values of objects remain optional when being checked in an if statement in Typescript?

Recently at work, I encountered this code snippet and was left wondering why Typescript couldn't comprehend the logic behind it. If 'test' in the object can either be undefined or a string, shouldn't it logically infer that within an if ...

Testing the mirkoORM entities at a unit level

Trying to perform a unit test on a method within a MikroORM entity, I am attempting to populate a mikroORM collection field with test data. Specifically, I am using jest for this task: describe('Team Tests', () => { it('isLeader shoul ...

Vue: Defining typed props interface including optional properties

I created a method that I want to be accessible on all my Vue instances, so I can use it in case of an error and display a specific error component. Similar to the functionality provided by vue-error-page. Since I am working with typescript, I now want to ...

Error: Unable to locate the type definition file for the '@babel' package

I am currently working on a new project and here is the content of my package.json file. { "name": "dapp-boilerplate", "version": "1.0.0", "main": "index.js", "license": "MI ...

Dealing with mistakes in an Angular service

I've been grappling with error handling in Angular. I attempted to handle errors within a service, but I'm uncertain if that's the correct approach. @Injectable({ providedIn: 'root', }) export class CaseListService { public con ...

Best .htaccess configuration for optimizing Next.js static site generation

When exporting a static site using NextJS, the file structure includes: |-- index.html |-- article.html |-- tag.html |-- article | |-- somearticle.html | \-- anotherarticle.html \-- tag |-- tag1.html \-- tag2.html To hide the . ...

When transitioning the Next application to Typescript, errors are displayed with JSX, but it functions correctly in the browser

After migrating my Next App from JS to TSX, I noticed that the JSX in my TSX file is showing errors and underlined, even though the app runs fine in the browser. I'm puzzled as to why this inconsistency exists. Can anyone provide assistance in resolvi ...

Executing the callback function

I am facing a situation where I have a Modelmenu nested within the parent component. It is responsible for opening a modal window upon click. Additionally, there is a child component in the same parent component that also needs to trigger the opening of a ...