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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With