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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.