7

I've been struggling to integrate Typescript with NextJS, mainly with destructured parameters in getInitialProps but also with the type of page functions. For example, here is my _app.tsx:

import { ThemeProvider } from 'styled-components';
import App, { Container } from 'next/app';
import Cookie from 'js-cookie';
import React from 'react';

import { CookiesProvider } from '../components/CookiesContext';
import THEME from '../styles/config';

import {
  GlobalStyles,
  Wrapper,
} from './_app.style';

type Props = {
  cookieSettings: {
    functionalOn: string;
    performanceOn: string;
  }
};

class Page extends App<Props> {
  static async getInitialProps({
    Component,
    ctx,
  }) {
    // Get initial page props
    const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};

    // Get cookies settings
    const cookieSettings = {
      functionalOn: process.browser ? Cookie.get('functionalCookies') : ctx.req.cookies.functionalCookies,
      performanceOn: process.browser ? Cookie.get('performanceCookies') : ctx.req.cookies.performanceCookies,
    };

    return {
      cookieSettings,
      pageProps,
    };
  }

  render() {
    const {
      Component,
      cookieSettings,
      pageProps,
    } = this.props;

    return (
      <Container>
        <ThemeProvider theme={THEME}>
          <CookiesProvider {...cookieSettings}>
            <Wrapper>
              <GlobalStyles />
              <Component {...pageProps} />
            </Wrapper>
          </CookiesProvider>
        </ThemeProvider>
      </Container>
    );
  }
}

export default Page;

The only error I get here is that the Component and ctx parameters are implicitly of 'any' type. I'm using @types/next, as well as v8.1.1.Canary.40 of NextJS which includes types, so I thought stuff like this would be covered but I seem to have to declare what they are myself and I don't know since it's a third party package.

Also, I have a page file like this:

import { NextPage } from 'next';
import React, { Fragment } from 'react';

import Metadata from '../components/Metadata';
import withPageError from '../components/PageError/withPageError';

type Props = {
  // TODO: Add props
};

const getInitialProps = async ({ res }) => {
  const page = await getPageData();
  if (!page && res) res.statusCode = 404;
  if (!page) return {};
  return { page };
};

const Page: NextPage<Props> = () => (
  <Fragment>
    <Metadata
      pageDescription="Page"
      pageTitle="Page"
      socialDescription="Page"
      socialTitle="Page"
    />
  </Fragment>
);

Page.getInitialProps = getInitialProps;

export default withPageError(Page);

Here I get red squigglies on Page.getInitialProps with the following error:

Type '({ res }: { res: any; }) => Promise<{ page?: undefined; } | { page: any; }>' is not assignable to type '(ctx: NextPageContext) => Promise<Props>'.

Also an error on const Page which is huge and doesn't make any sense to me.

What am I missing in all of this? Surely I don't have to redeclare types for a load of NextJS stuff?

0

3 Answers 3

3

You just need to type getInitialProps, like that:

import React from 'react'
import { NextPageContext } from 'next'

interface Props {
  userAgent?: string;
}

export default class Page extends React.Component<Props> {
  static async getInitialProps({ req }: NextPageContext) {
    const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
    return { userAgent }
  }

  render() {
    const { userAgent } = this.props
    return <main>Your user agent: {userAgent}</main>
  }
}

Next.js docs - https://nextjs.org/docs/api-reference/data-fetching/getInitialProps

Sign up to request clarification or add additional context in comments.

Comments

2

The getInitialProps should return a Props type object. But it returns { page } and the property page does not exist in Page type.

Comments

0

Pull in the AppProps to get access to the properties of the application.

import { AppProps } from 'next/app'
 

export default function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.