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


