TypeScript Next.js ESLint の設定でハマったついでにクリーンな環境で Next.js の ESLint で TypeScript のエラー表示させる方法までを試したのでメモ代わりに残しておきます
環境
- Next.js
13.2.1
- react
18.2.0
- typescript:
4.9.5
- eslint
8.35.0
Next.js のプロジェクト作成
$ npx create-next-app <PROJECT NAME> --typescript ✔ Would you like to use ESLint with this project? … Yes ✔ Would you like to use `src/` directory with this project? … Yes ✔ Would you like to use experimental `app/` directory with this project? … Yes ✔ What import alias would you like configured? … @/*
デフォルトの ESLint
.eslintrc.json
{ "extends": ["next/core-web-vitals"] }
TypeScript 的にやばいコンポーネントを作成する
React Component/src/MyComponent.tsx
import { FC } from "react"; type MyComponentProps = { name: string; }; export const MyComponent: FC = ({ user }) => { const foo = user(); const bar: any = user; return <div>{user.name} {user.age} {foo} {bar}</div> };
MyComponentProps
-> 使われてない変数const MyComponent: FC = ({ user }
->user
が anyconst foo = user();
-> any 型に対してメソッドの呼び出しconst bar: any = user;
-> any 型の宣言,bar
は使用されてない変数{user.name} {user.age}
-> any 型のプロパティアクセス
Next Page /src/app/sample/page.tsx
import { NextPage } from "next"; const SamplePage: NextPage = ({ members }) => { return <div>{members.map((user) => (<div key={user.id} >{user.name}</div>))}</div> }; export default SamplePage;
const SamplePage: NextPage = ({ members })
->members
は any 型members.map((user) => (<div key={user.id} >{user.name}</div>))
- -> any型の
members
に対して.map
の実行 - ->
user
は any 型 - -> any 型の
user
のプロパティにアクセス
- -> any型の
📝 デフォルトの ESLint では TypeScript のエラーが出ない
$ npm run lint ✔ No ESLint warnings or errors
.tsconfig.json
は "strict": true
だが ESLint で any のエラーなどを拾うことができない状態…
Next.js の ESLint で TypeScript のエラーを表示するようにする
$ npm i -D @typescript-eslint/eslint-plugin
未使用の変数と any の型指定に warning を表示させる設定を .eslintrc.json
に追加した
{ - "extends": ["next/core-web-vitals"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "next/core-web-vitals" + ], + "rules": { + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-explicit-any": "warn" + } }
👇 ESLint の実行
$ npm run lint ./src/MyComponent.tsx 3:6 Warning: 'MyComponentProps' is defined but never used. @typescript-eslint/no-unused-vars 9:9 Warning: 'bar' is assigned a value but never used. @typescript-eslint/no-unused-vars 9:14 Warning: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
意図したとおりに Warning が表示されている
any に対するルールの追加
no-unsafe-call
… any型に対する関数呼び出し(anyVal()など)を禁止します。no-unsafe-member-access
… any型に対するメンバ呼び出し(anyVal.hogeやanyVal['hoge']など)を禁止します。no-unsafe-return
… anyかany[]が引数の返り値になることを禁止します。cf. typescript-eslintの最新オプションno-unsafe-*を使って、TypeScriptの型リファクタリングを簡単に行った話 - ITANDI Engineer Blog
.eslintrc.json
を編集する
{ "extends": [ "plugin:@typescript-eslint/recommended", "next/core-web-vitals" ], + "parserOptions": { + "project": "./tsconfig.json" + }, "rules": { "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-unsafe-call": "error", + "@typescript-eslint/no-unsafe-member-access": "error", + "@typescript-eslint/no-unsafe-return": "error" } }
※ 違いが見やすいように "error"
の指定にした
⚠ no-unsafe-call
, no-unsafe-member-access
, no-unsafe-return
のルールを使うには parserOptions.project
にプロジェクトの tsconfig
を指定する必要がある
指定してないと lint 実行時に次のようなエラーになる
=> Error while loading rule '@typescript-eslint/no-unsafe-call': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
👇 ESLint の実行
$ npm run lint ./src/MyComponent.tsx 3:6 Warning: 'MyComponentProps' is defined but never used. @typescript-eslint/no-unused-vars 8:15 Error: Unsafe call of an `any` typed value. @typescript-eslint/no-unsafe-call 9:9 Warning: 'bar' is assigned a value but never used. @typescript-eslint/no-unused-vars 9:14 Warning: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any 10:29 Error: Unsafe member access .name on an `any` value. @typescript-eslint/no-unsafe-member-access 10:41 Error: Unsafe member access .age on an `any` value. @typescript-eslint/no-unsafe-member-access ./src/app/sample/page.tsx 4:16 Error: Unsafe member access .map on an `any` value. @typescript-eslint/no-unsafe-member-access 4:16 Error: Unsafe call of an `any` typed value. @typescript-eslint/no-unsafe-call 4:49 Error: Unsafe member access .id on an `any` value. @typescript-eslint/no-unsafe-member-access 4:60 Error: Unsafe member access .name on an `any` value. @typescript-eslint/no-unsafe-member-access
先程は表示されなかった any 型のオブジェクトに対するアクセスにもルール通りエラーが表示されるようになった!
まとめ
- Next.js はデフォルトでは TypeScript のエラーが
npm run lint
では表示されない - ミニマムな TypeScript のエラーを表示させるには
@typescript-eslint/eslint-plugin
をインストールして.eslintrc.json
にルールを追加する - 使用するルールに依っては
.eslintrc.json
にparserOptions.project
プロパティを作成しプロジェクトのtsconfig.json
のパスを指定する
自分で試した結果なので、勘違いなどあるかもしれません :pray:
おわり ₍ ᐢ. ̫ .ᐢ ₎
[参考]
- Configuring: TypeScript | Next.js
- Configuring: ESLint | Next.js
- https://www.sandromaglione.com/techblog/create-nextjs-project-with-typescript-eslint-prettier-tailwindcss
- Next.js (TypeScript) に ESLint と Prettier を導入し、コードを綺麗に保とう | fwywd(フュード)powered by キカガク
- うわっ...私の.eslintrc、無駄が多すぎ...?
- typescript-eslintの最新オプションno-unsafe-*を使って、TypeScriptの型リファクタリングを簡単に行った話 - ITANDI Engineer Blog
- Next.js 13 app directory で記事投稿サイトを作ってみよう
- microCMS × Next.js(TypeScript)で個人ブログを作る #TypeScript - Qiita