create-next-appで作成したNext.jsアプリケーションをTypeScriptで動くようにする

Next.jsのアプリケーションを簡単に作るcreate-next-appというものを知ったので、これで作ったものをTypeScriptで動くようにしてみました。 セットアップ create-next-appでさっと作っ […]

広告ここから
広告ここまで

目次

    Next.jsのアプリケーションを簡単に作るcreate-next-appというものを知ったので、これで作ったものをTypeScriptで動くようにしてみました。

    セットアップ

    create-next-appでさっと作っておきましょう。

    $ npx create-next-app my-first-next-app
    $ cd my-first-next-app

    TypeScriptセットアップ

    tsconfig.jsonを配置します。

    $ touch tsconfig.json

    不足しているライブラリを指摘してくるので、コピペして追加しましょう。

    $ yarn dev
    [ wait ]  starting the development server ...
    [ info ]  waiting on https://localhost:3000 ...
    It looks like you're trying to use TypeScript but do not have the required package(s) installed.
    
    Please install typescript, @types/react, and @types/node by running:
    
        yarn add --dev typescript @types/react @types/node
    
    If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files).
    
    error Command failed with exit code 1.
    
    $ yarn add --dev typescript @types/react @types/node

    もう一度yarn devを実行すると、tsconfig.jsonの中身が生成されます。

    $ yarn dev
    yarn run v1.16.0
    $ next dev
    [ wait ]  starting the development server ...
    [ info ]  waiting on https://localhost:3000 ...
    We detected TypeScript in your project and created a tsconfig.json file for you.
    
    Your tsconfig.json has been populated with default values.
    
    [ info ]  bundled successfully, waiting for typecheck results...

    作成されたtsconfig.json

    {
      "compilerOptions": {
        "target": "es5",
        "lib": [
          "dom",
          "dom.iterable",
          "esnext"
        ],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": false,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve"
      },
      "exclude": [
        "node_modules"
      ],
      "include": [
        "next-env.d.ts",
        "**/*.ts",
        "**/*.tsx"
      ]
    }
    

    js -> tsx

    create-next-appで作成した場合、pages/index.jscomponents/nav.jsの2ファイルでReactのJSXが記述されています。これを拡張子tsxに変えましょう。

    変更すると、TypeScriptのエラーが出ます。

    [ error ] ERROR in /Users/develop/site/components/nav.tsx(8,8):
    8:8 Property 'key' does not exist on type '{ href: string; label: string; }'.
         6 |   { href: 'https://github.com/zeit/next.js', label: 'GitHub' },
         7 | ].map(link => {
      >  8 |   link.key = `nav-link-${link.href}-${link.label}`
           |        ^
         9 |   return link
        10 | })
        11 | 
    undefined
    undefined

    nav.tsxlinksの型に問題がある様子です。

    TypeScriptのコンパイルエラーを解決する

    linksは以下のような定義がされています。

    const links = [
      { href: 'https://zeit.co/now', label: 'ZEIT' },
      { href: 'https://github.com/zeit/next.js', label: 'GitHub' },
    ].map(link => {
      link.key = `nav-link-${link.href}-${link.label}`
      return link
    })

    ここで問題になっているのは、keyプロパティです。はじめの定義ではhreflabelの2プロパティしかありません。そのために型推論ではこの2つだけを持つ配列を判断されています。そこに後続のmapで未定義のkeyプロパティを追加しようとしているためにエラーがでています。

    これを解決するシンプルな方法は、プロパティの追加方法を変更することです。

    const links = [
      { href: 'https://zeit.co/now', label: 'ZEIT' },
      { href: 'https://github.com/zeit/next.js', label: 'GitHub' },
    ].map(link => {
      return {
        ...link,
        key: `nav-link-${link.href}-${link.label}`
      }
    })

    型推論がすでに行われているlinkに直接追加するのではなく、新しいオブジェクトとしてreturnさせました。これでlinkshref, label, keyの3プロパティをもつ配列と推論されるようになります。

    おわりに

    ボイラープレートをJavaScriptからTypeScriptに変換しただけの簡単なサンプルでしたので、手数はかなり少なめでした。

    tsconfig.jsonを自動生成してくれるのは個人的には好感をもてます。ブラックボックスにされていない点も含めて。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark