最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Typescript with NextJS - Stack Overflow

programmeradmin4浏览0评论

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-ponents';
import App, { Container } from 'next/app';
import Cookie from 'js-cookie';
import React from 'react';

import { CookiesProvider } from '../ponents/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 '../ponents/Metadata';
import withPageError from '../ponents/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?

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-ponents';
import App, { Container } from 'next/app';
import Cookie from 'js-cookie';
import React from 'react';

import { CookiesProvider } from '../ponents/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 '../ponents/Metadata';
import withPageError from '../ponents/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?

Share Improve this question asked May 29, 2019 at 15:23 CaribouCodeCaribouCode 14.4k33 gold badges111 silver badges186 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 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/docs/api-reference/data-fetching/getInitialProps

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

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} />
}
发布评论

评论列表(0)

  1. 暂无评论