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.js
とcomponents/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.tsx
のlinks
の型に問題がある様子です。
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
プロパティです。はじめの定義ではhref
とlabel
の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させました。これでlinks
はhref
, label
, key
の3プロパティをもつ配列と推論されるようになります。
おわりに
ボイラープレートをJavaScriptからTypeScriptに変換しただけの簡単なサンプルでしたので、手数はかなり少なめでした。
tsconfig.jsonを自動生成してくれるのは個人的には好感をもてます。ブラックボックスにされていない点も含めて。