使用TypeScript在Next.js中使用getInitialProps

时间:2018-04-19 19:58:29

标签: typescript definitelytyped nextjs

从文档,Next.js 5.0公告和互联网上的各种文章看来,Next.js很好地支持TypeScript,很多人都在使用它。

但是这些主题表明getInitialProps对Next.js应用程序至关重要,但不起作用:

我该如何解决?在类和功能组件中,当我ComponentName.getInitialProps = async function() {...}时,我收到以下错误:

[ts] Property 'getInitialProps' does not exist on type '({ data }: { data: any; }) => Element'.

6 个答案:

答案 0 :(得分:25)

自从Next.js现在正式支持TypeScript(公告here)以来,上述答案已经过时了

此发行版的一部分是更好的TypeScript类型,其中许多Next.js都是用TypeScript本身编写的。这意味着set包将被弃用,而支持Next.js的官方输入。

相反,您应该导入NextPage type并将其分配给您的组件。您也可以使用@types/next类型输入getInitialProps

NextPageContext

答案 1 :(得分:17)

解决问题的经典方法是将getInitialProps声明为静态成员:

class MyComponent extends React.Component<{...}, {}> {

  static async getInitialProps(ctx: any) {
    return {...}
  }

  render() {...}

}

使用无状态组件时,您可以声明React.SFC的简单扩展名:

interface StatelessPage<P = {}> extends React.SFC<P> {
  getInitialProps?: (ctx: any) => Promise<P>
}

const MyComponent: StatelessPage<{...}> = (...) => ...

MyComponent.getInitialProps = async (ctx) => {...}

答案 2 :(得分:6)

Next.js的类型在DefinitelyTyped project中维护,该版本具有新版本7.0.6。

为了使用新类型,请确保将它们导入到项目中:

npm install --save-dev @types/next@7.0.6

这是您为无状态功能组件键入getInitialProps的方式:

import { NextFunctionComponent, NextContext } from 'next'

// Define what an individual item looks like
interface IDataObject {
  id: number,
  name: string
}

// Define the props that getInitialProps will inject into the component
interface IListComponentProps {
  items: IDataObject[]
}

const List: NextFunctionComponent<IListComponentProps> = ({ items }) => (
  <ul>
    {items.map((item) => (
      <li key={item.id}>
        {item.id} -- {item.name}
      </li>
    ))}
  </ul>
)

List.getInitialProps = async ({ pathname }: NextContext) => {
  const dataArray: IDataObject[] =
    [{ id: 101, name: 'larry' }, { id: 102, name: 'sam' }, { id: 103, name: 'jill' }, { id: 104, name: pathname }]

  return { items: dataArray }
}

export default List

这是您为课程输入getInitialProps的方式:

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

// Define what an individual item looks like
interface IDataObject {
  id: number,
  name: string
}

// Define the props that getInitialProps will inject into the component
interface IListClassProps {
  items: IDataObject[]
}

class List extends React.Component<IListClassProps> {
  static async getInitialProps({ pathname }: NextContext) {
    const dataArray: IDataObject[] =
      [{ id: 101, name: 'larry' }, { id: 102, name: 'sam' }, { id: 103, name: 'jill' }, { id: 104, name: pathname }]

    return { items: dataArray }
  }

  render() {
    return (
      <ul>
        {this.props.items.map((item) => (
          <li key={item.id}>
            {item.id} -- {item.name}
          </li>
        ))}
      </ul>
    )
  }
}

export default List

如果您查看tests in DefinitelyTyped,则会获得很多有关如何在Next中使用其他类型的输入的见解。

答案 3 :(得分:0)

遵循文档

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>
  }
}

答案 4 :(得分:0)

简单的解决方案是声明类型:

declare global {
   namespace React {
      interface FunctionComponent<P = {}> {
      getInitialProps(): void;
}}}

答案 5 :(得分:-6)

这不是一个真正的解决方案,但可能的解决方法是仅将TypeScript用于服务器端和通用脚本(.ts扩展名)。

对于React组件,请使用.jsx扩展名并放弃TypeScript。可以使用prop-typesprop-types-exact - 它们会对道具进行类型检查(使用npm安装包)。