【key-front】tsconfig/basesのすゝめ
モチベーション
- 毎週木曜日Slackのkey_frontチャンネルでハドル機能を使いお題に対してメンバー同士ディスカッションをする時間を15〜30分程度設けている
- 今回はtsconfig/basesについて取り上げる
- ファシリテーターは筆者なので、事前に読み込んで気になった点などをスクラップに投げていく
- 開催日は〇〇/〇〇(木)で最終的に議事録として結論をまとめる
背景
下記のLTに参加してtsconfig/basesの存在を知ったのでアウトプットする
tsconfig/bases
Strictest
インストール
npm install --save-dev @tsconfig/strictest
yarn add --dev @tsconfig/strictest
"strict": true
"allowUnusedLabels": false,
"allowUnreachableCode": false,
"exactOptionalPropertyTypes": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"isolatedModules": true,
"checkJs": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
Next.js
インストール
npm install --save-dev @tsconfig/next
yarn add --dev @tsconfig/next
※上記と同じオプションは省略する
"lib": ["dom", "dom.iterable", "esnext"],
"noEmit": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"jsx": "preserve",
特になし
"incremental": true,
"plugins": [ { "name": "next" } ]
補足
Denoのtsconfigのデフォルト設定
What about combined configs?
TypeScriptの構成拡張システムの以前の制約のため、このリポジトリはNode + ESM、Node + Strictestなどいくつかの共通ベースから結合された構成を提供していました。
しかし、TypeScript v5.0.0では複数の構成を一度に拡張できる機能が提供されており、この問題はもはや存在しません。例えば、Node 18 + Strictestベースの構成から始めたい場合、@tsconfig/node18と@tsconfig/strictestパッケージの両方をインストールし、それらの構成を次のように拡張できます:
// tsconfig.json
{
"extends": ["@tsconfig/strictest/tsconfig", "@tsconfig/node18/tsconfig"]
}
なのでNext.jsでプロジェクトを始める際は下記で設定してあげるとより堅牢な実装ができる(スタックによってFWは異なると思うのでREADMEを見てください)
// tsconfig.json
{
"extends": ["@tsconfig/strictest/tsconfig", "@tsconfig/next/tsconfig"]
}
create-next-app後のtsconfig.jsonの中身
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
@tsconfig/nextとの差分
{
"extends": ["@tsconfig/next/tsconfig"],
"compilerOptions": {
"target": "es5",
// "lib": ["dom", "dom.iterable", "esnext"],
// "allowJs": true,
// "skipLibCheck": true,
// "strict": true,
// "noEmit": true,
// "esModuleInterop": true,
// "module": "esnext",
// "moduleResolution": "bundler",
// "resolveJsonModule": true,
// "isolatedModules": true,
// "jsx": "preserve",
// "incremental": true,
// "plugins": [
// {
// "name": "next"
// }
// ],
"paths": {
"@/*": ["./*"]
}
},
// "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
// "exclude": ["node_modules"]
}
@tsconfig/strictestも加えてカスタマイズする
{
"extends": ["@tsconfig/strictest/tsconfig", "@tsconfig/next/tsconfig"],
"compilerOptions": {
"target": "es5",
"exactOptionalPropertyTypes": false,
"noImplicitOverride": false,
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"] // @tsconfigだとみている場所が違う?
}
strictestを2.0.3 -> 2.0.5へバージョンアップするとエラーが発生
strictestを2.0.3 -> 2.0.5にアップデートした際に以下のエラーが発生した。2.0.3から2.0.5で何が変更されたのかまとめていく
具体的に発生したエラー内容
Error: Uncaught [TypeError: (0 , _react1.useMemo) is not a function]
Uncaught [Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
@2.0.3
@2.0.3
{
"compilerOptions": {
"strict": true,
"allowUnusedLabels": false,
"allowUnreachableCode": false,
"exactOptionalPropertyTypes": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"isolatedModules": true,
"checkJs": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Strictest",
"_version": "2.0.0"
}
@2.0.5
@2.0.5
{
"compilerOptions": {
"strict": true,
"allowUnusedLabels": false,
"allowUnreachableCode": false,
"exactOptionalPropertyTypes": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"isolatedModules": true,
"checkJs": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"$schema": "https://json.schemastore.org/tsconfig",
"_version": "2.0.0"
}
どのような差分が生まれていたのか?
strictestを2.0.3 -> 2.0.5へバージョンアップするとforceConsistentCasingInFileNames: true
が新しく追加されていることがわかった
forceConsistentCasingInFileNamesとはなにか?
↓必要そうな部分をdeeplに入れてみる
TypeScriptは、実行するファイルシステムの大文字と小文字を区別するルールに従います。 これは、大文字と小文字を区別するファイルシステムで作業している開発者と、そうでない開発者がいる場合に問題となる可能性がある。
./FileManager.tsを指定してfileManager.tsをインポートしようとすると、大文字小文字を区別しないファイルシステムではそのファイルが見つかるが、大文字小文字を区別するファイルシステムでは見つからない。
一旦2.0.3 -> 2.0.5での差分について理解できたのでクローズさせる。色々調査してみたがforceConsistentCasingInFileNamesがはじめに触れたエラーに関わっているとは思えないので別のところでエラーが発生しているのかもしれない。