CLOVER🍀

That was when it all began.

TSConfig Basesでtsconfig.jsonの推奨設定を確認する

これは、なにをしたくて書いたもの?

tsconfig.jsonにどういうものを指定したらいいんだろう?という気になるのですが、なにか参考になるものが欲しいところです。

このような目的でTSConfig Basesというものがあるらしいので、少し見てみました。

TSConfig Bases

TSConfig BasesはTypteScriptのドキュメントで紹介されています。

Depending on the JavaScript runtime environment which you intend to run your code in, there may be a base configuration which you can use at github.com/tsconfig/bases. These are tsconfig.json files which your project extends from which simplifies your tsconfig.json by handling the runtime support.

What is a tsconfig.json / TSConfig Bases

リファレンスの方には載っていないのですが…。

TSConfig Basesは特定のランタイム環境に合わせて調整された、tsconfig.jsonをホストしたものです。
GitHubリポジトリーはこちら。

GitHub - tsconfig/bases: Hosts TSConfigs to extend in a TypeScript app, tuned to a particular runtime environment

使い方はドキュメントに書かれているように、パッケージマネージャーでインストールして

$ npm install --save-dev @tsconfig/recommended
$ yarn add --dev @tsconfig/recommended

tsconfig.jsonextendsします。

"extends": "@tsconfig/recommended/tsconfig.json"

これはRecommendedを使った例です。

現時点で、これだけの種類があります。

名前 npmパッケージ名
Recommended @tsconfig/recommended
Bun @tsconfig/bun
Create React App @tsconfig/create-react-app
Cypress @tsconfig/cypress
Deno @tsconfig/deno
Docusaurus v2 @tsconfig/docusaurus
Ember @tsconfig/ember
Next.js @tsconfig/next
Node LTS @tsconfig/node-lts
Node 10 @tsconfig/node10
Node 12 @tsconfig/node12
Node 14 @tsconfig/node14
Node 16 @tsconfig/node16
Node 17 @tsconfig/node17
Node 18 @tsconfig/node18
Node 19 @tsconfig/node19
Node 20 @tsconfig/node20
Node 21 @tsconfig/node21
Node 22 @tsconfig/node22
Nuxt @tsconfig/nuxt
React Native @tsconfig/react-native
Remix @tsconfig/remix
Strictest @tsconfig/strictest
Svelte @tsconfig/svelte
Taro @tsconfig/taro
Vite React @tsconfig/vite-react

RecommendedとStrictestはちょっと気になるところ。あとは使う環境に応じて、各ランタイムやフレームワーク向けのものを見ていく
感じでしょうか。

どのような設定になっているかは、README.mdのリンクから各パッケージのnpm上でのドキュメントを見るか、

@tsconfig/recommended - npm

@tsconfig/strictest - npm

@tsconfig/node20 - npm

直接ソースコードを見てもよいでしょう。

https://github.com/tsconfig/bases/blob/15ede8eb165ac58391c66724887be03608d6c1e8/bases/recommended.json

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

https://github.com/tsconfig/bases/blob/ebe629c2857d386a0bc2c5d60cab18b9f1a425d0/bases/node20.json

リリースタグはないので、コミットハッシュを見るしかなさそうですね。

また、こういうファイルの用意のされかたを見ると、「Recommended+Node.js 20」のような設定がしたいと思ったりするのですが、
組み合わせ方はこちらに書いています。

Centralized Recommendations for TSConfig bases / What about combined configs?

以前はtsconfig.jsonextendsをひとつしか指定できなかったので、このリポジトリーでも組み合わせの構成を提供していたようです。
TypeScript 5.0以降はextendsが拡張されて複数の指定が可能になったので、利用者側で組み合わせられるようになりました。

以下はREADME.mdに載っているStrictest(最も厳しい)+Node.js 18の例です。

// tsconfig.json
{
  "extends": ["@tsconfig/strictest/tsconfig", "@tsconfig/node18/tsconfig"]
}

このテーマだけを独立させて書いたのが、こちらのエントリーだったりします。

TypeScript 5.0からtsconfig.jsonのextends元を複数指定できるようになっていたという話(+showConfigで最終結果確認) - CLOVER🍀

こんな感じでだいたい使い方の雰囲気はわかったのですが、簡単に試しておきましょう。

環境

今回の環境はこちら。

$ node --version
v20.16.0


$ npm --version
10.8.1

準備

Node.jsプロジェクトを作成して、TypeScriptをインストール。

$ npm init -y
$ npm i -D typescript
$ npm i -D @types/node@v20

バージョン。

  "devDependencies": {
    "@types/node": "^20.14.8",
    "typescript": "^5.5.4"
  }

あとでextendsを追加するためのtsconfig.jsonも作成しておきます。

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "outDir": "dist"
  },
  "include": [
    "src/**/*"
  ]
}

トランスパイル用のダミーのソースコードも作成。

$ mkdir src
$ echo "console.log('Hello World');" > src/hello.ts

tscが動作するところまでは確認しておきます。

$ npx tsc

TSConfig Basesをベースにtsconfig.jsonを作成する

それでは、TSConfig Basesを使ってみましょう。

まずはNode.js 20用のtsconfig.jsonをインストールしてみます。

$ npm i -D @tsconfig/node20

依存関係はこうなりました。

  "devDependencies": {
    "@tsconfig/node20": "^20.1.4",
    "@types/node": "^20.14.8",
    "typescript": "^5.5.4"
  }

これをtsconfig.jsonextendsに追加します。

tsconfig.json

{
  "extends": "@tsconfig/node20/tsconfig.json",
  "compilerOptions": {
    "baseUrl": "./src",
    "outDir": "dist"
  },
  "include": [
    "src/**/*"
  ]
}

--showConfigフラグで最終結果を表示してみます。

$ npx tsc --showConfig
{
    "compilerOptions": {
        "lib": [
            "es2023"
        ],
        "module": "node16",
        "target": "es2022",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "moduleResolution": "node16",
        "baseUrl": "./src",
        "outDir": "./dist",
        "moduleDetection": "force",
        "allowSyntheticDefaultImports": true,
        "resolvePackageJsonExports": true,
        "resolvePackageJsonImports": true,
        "useDefineForClassFields": true,
        "noImplicitAny": true,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "strictBindCallApply": true,
        "strictPropertyInitialization": true,
        "alwaysStrict": true,
        "useUnknownInCatchVariables": true
    },
    "files": [
        "./src/hello.ts"
    ],
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "/path/to/dist"
    ]
}

めちゃくちゃ増えましたね…。

Node.js 20のtsconfig.jsonの内容を見ると、stricttrueになっているのでここが効いているんでしょうね。

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node 20",
  "_version": "20.1.0",

  "compilerOptions": {
    "lib": ["es2023"],
    "module": "node16",
    "target": "es2022",

    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "node16"
  }
}

https://github.com/tsconfig/bases/blob/ebe629c2857d386a0bc2c5d60cab18b9f1a425d0/bases/node20.json

ではここに、さらにRecommendedも追加してみましょう。Node.js 20と同時に指定します。

インストール。

$ npm i -D @tsconfig/recommended

バージョン。

  "devDependencies": {
    "@tsconfig/node20": "^20.1.4",
    "@tsconfig/recommended": "^1.0.7",
    "@types/node": "^20.14.8",
    "typescript": "^5.5.4"
  }

Node.js 20とはまったくバージョン体系が違いますね…。というか、Node.jsの他のバージョンを見るとランタイムのバージョンを反映してそうな
感じがします。

tsconfig.jsonextendsに追加してみます。

tsconfig.json

{
  "extends": [
    "@tsconfig/recommended/tsconfig.json",
    "@tsconfig/node20/tsconfig.json"
  ],
  "compilerOptions": {
    "baseUrl": "./src",
    "outDir": "dist"
  },
  "include": [
    "src/**/*"
  ]
}

終結果。

$ npx tsc --showConfig
{
    "compilerOptions": {
        "target": "es2022",
        "module": "node16",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true,
        "lib": [
            "es2023"
        ],
        "moduleResolution": "node16",
        "baseUrl": "./src",
        "outDir": "./dist",
        "moduleDetection": "force",
        "allowSyntheticDefaultImports": true,
        "resolvePackageJsonExports": true,
        "resolvePackageJsonImports": true,
        "useDefineForClassFields": true,
        "noImplicitAny": true,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "strictBindCallApply": true,
        "strictPropertyInitialization": true,
        "alwaysStrict": true,
        "useUnknownInCatchVariables": true
    },
    "files": [
        "./src/hello.ts"
    ],
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "/path/to/dist"
    ]
}

差を見ると、この組み合わせではforceConsistentCasingInFileNamestrueになったくらいですね。RecommendedとNode.js 20で
かなり重複していそうです。

Recommendedの中身を見ると実際そんな感じでしたが、modulecommonjsなのでこの組み合わせとする場合はNode.js 20を後ろに
指定した方がよさそうですね。extendsで複数した場合にオプションが重複した場合は、後ろに置いた内容の方で上書きされるので。

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "display": "Recommended",
  "$schema": "https://json.schemastore.org/tsconfig"
}

https://github.com/tsconfig/bases/blob/15ede8eb165ac58391c66724887be03608d6c1e8/bases/recommended.json

こんな感じでしょうか。

あとはStrictestも見た方がいいかもしれません。

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

おわりに

TSConfig Basesを使って、tsconfig.jsonの推奨設定を確認してみました。

これらの設定を直接使うことがあるかはわかりませんが、tsconfig.jsonの設定をどうしたらいいか悩むことは多い気がするので、このあたりの
ファイルを参考にできることを覚えておいてもいいのではないかなと思います。