Closed8

【key-front】tsconfig/basesのすゝめ

1zushun1zushun

モチベーション

  • 毎週木曜日Slackのkey_frontチャンネルでハドル機能を使いお題に対してメンバー同士ディスカッションをする時間を15〜30分程度設けている
  • 今回はtsconfig/basesについて取り上げる
  • ファシリテーターは筆者なので、事前に読み込んで気になった点などをスクラップに投げていく
  • 開催日は〇〇/〇〇(木)で最終的に議事録として結論をまとめる
1zushun1zushun

Strictest

https://github.com/tsconfig/bases/blob/main/bases/strictest.json

インストール

npm install --save-dev @tsconfig/strictest
yarn add --dev @tsconfig/strictest

"strict": true

https://typescriptbook.jp/reference/tsconfig/strict

"allowUnusedLabels": false,

https://www.typescriptlang.org/ja/tsconfig#allowUnusedLabels

"allowUnreachableCode": false,

https://www.typescriptlang.org/ja/tsconfig#allowUnreachableCode

"exactOptionalPropertyTypes": true,

https://www.typescriptlang.org/ja/tsconfig#exactOptionalPropertyTypes

"noFallthroughCasesInSwitch": true,

https://www.typescriptlang.org/ja/tsconfig#noFallthroughCasesInSwitch

"noImplicitOverride": true,

https://www.typescriptlang.org/ja/tsconfig#noImplicitOverride

"noImplicitReturns": true,

https://www.typescriptlang.org/ja/tsconfig#noImplicitReturns

"noPropertyAccessFromIndexSignature": true,

https://www.typescriptlang.org/ja/tsconfig#noPropertyAccessFromIndexSignature

"noUncheckedIndexedAccess": true,

https://www.typescriptlang.org/ja/tsconfig#noUncheckedIndexedAccess

"noUnusedLocals": true,

https://www.typescriptlang.org/ja/tsconfig#noUnusedLocals

"noUnusedParameters": true,

https://www.typescriptlang.org/ja/tsconfig#noUnusedParameters

"isolatedModules": true,

https://www.typescriptlang.org/ja/tsconfig#isolatedModules

"checkJs": true,

https://www.typescriptlang.org/ja/tsconfig#checkJs

"esModuleInterop": true,

https://www.typescriptlang.org/ja/tsconfig#esModuleInterop

"skipLibCheck": true,

https://www.typescriptlang.org/ja/tsconfig#skipLibCheck

"forceConsistentCasingInFileNames": true

https://www.typescriptlang.org/ja/tsconfig#forceConsistentCasingInFileNames

1zushun1zushun

Next.js

https://github.com/tsconfig/bases/blob/main/bases/next.json

インストール

npm install --save-dev @tsconfig/next
yarn add --dev @tsconfig/next

※上記と同じオプションは省略する

"lib": ["dom", "dom.iterable", "esnext"],

https://typescriptbook.jp/reference/tsconfig/tsconfig.json-settings#lib

"noEmit": true,

https://www.typescriptlang.org/ja/tsconfig#noEmit

"module": "esnext",

https://typescriptbook.jp/reference/tsconfig/tsconfig.json-settings#module

"moduleResolution": "bundler",

https://github.com/tsconfig/bases/pull/197

"resolveJsonModule": true,

https://www.typescriptlang.org/ja/tsconfig#resolveJsonModule

"jsx": "preserve",

特になし

"incremental": true,

https://www.typescriptlang.org/ja/tsconfig#incremental

"plugins": [ { "name": "next" } ]

1zushun1zushun

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"]
}
1zushun1zushun
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だとみている場所が違う?
}
1zushun1zushun

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.

https://cpoint-lab.co.jp/article/202005/15172/

@2.0.3

https://www.npmjs.com/package/@tsconfig/strictest/v/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

https://www.npmjs.com/package/@tsconfig/strictest/v/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をインポートしようとすると、大文字小文字を区別しないファイルシステムではそのファイルが見つかるが、大文字小文字を区別するファイルシステムでは見つからない。

https://www.typescriptlang.org/tsconfig/#forceConsistentCasingInFileNames

一旦2.0.3 -> 2.0.5での差分について理解できたのでクローズさせる。色々調査してみたがforceConsistentCasingInFileNamesがはじめに触れたエラーに関わっているとは思えないので別のところでエラーが発生しているのかもしれない。

このスクラップは2023/11/24にクローズされました