Skip to content

Commit

Permalink
chore: bump typescript version to 5.2.2, remove CommonJS and update s… (
Browse files Browse the repository at this point in the history
#1059)

…cripts and configs

## 作業内容

- TypeScript のバージョンを v5.2.2 に更新
- これに伴い Markdown を React で読み込んでいる箇所でエラーが出るようになってしまったため、 `@mdx-js/rollup`
を使うように変更
  - ESModule 化
- 上記変更により依存スクリプトを ESModule 形式に統一する必要が生じたため、これを機に mono repo 全体で CommonJS
形式のスクリプトをすべて ESModule に刷新する作業を行った。
- eslint config を ESModule 形式にするためには Flat Config の導入が必要だったためこれを行った。
- eslint-utils local package を作成し、 TypeScript で config を記述するように変更した。
- package.json, eslint.config.js, vite.config.ts, tsconfig.json
等を自動生成するスクリプトを作成
- strict-ts-lib の作成
  - typescript のカスタム lib 定義を `/// <reference />` 無しで読み込めるようにした。
  -
  • Loading branch information
noshiro-pf authored Jan 14, 2024
1 parent 2f00da4 commit 2377f25
Show file tree
Hide file tree
Showing 3,457 changed files with 329,315 additions and 180,965 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
5 changes: 5 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"argparse",
"asciz",
"astish",
"asyncgenerator",
"asynciterable",
"autofix",
"automl",
"autoplay",
Expand Down Expand Up @@ -92,6 +94,7 @@
"idiv",
"iife",
"immer",
"importscripts",
"imul",
"infty",
"iset",
Expand Down Expand Up @@ -213,6 +216,7 @@
"tses",
"tsutils",
"typecheck",
"typedarrays",
"typeof",
"unbundle",
"uncapitalize",
Expand All @@ -233,6 +237,7 @@
"vitestw",
"vnode",
"wantedly",
"weakref",
"webfonts",
"whitespaces",
"wirecut",
Expand Down
5 changes: 3 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
root = true

[*]
charset = utf-8
end_of_line = lf
Expand All @@ -6,13 +8,12 @@ indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
[*.{md,mdx}]
indent_size = 4
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
indent_size = 2

[Dockerfile]
indent_size = 4
3 changes: 1 addition & 2 deletions .github/workflows/e2e-apps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ on:
- 'books/**'
- 'docs/**'
- 'experimental/**'
- 'config/eslintrc/**'
- 'packages/slides/**'
- 'packages/others/**'
- 'packages/tools/**'
Expand Down Expand Up @@ -144,7 +143,7 @@ jobs:
working-directory: packages/apps/event-schedule-app
spec: cypress/e2e/**/*.cy.ts
start: |
yarn z:fb:emulators:start:e2e
yarn start:emulators:e2e
yarn start:dev-server
# wait-on: 'http://localhost:8080, http://localhost:8081, http://localhost:5001'
wait-on: 'http://localhost:5180'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ jobs:
yarn ws:build
yarn zz:cmd:check:no-diff
- name: type-check:root
run: yarn type-check:root
- name: type-check:scripts
run: yarn type-check:scripts

- name: ws:type-check
run: yarn ws:type-check
Expand Down
6 changes: 0 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ experimental/**/esm
experimental/**/cjs
experimental/**/config/**/*.js
experimental/**/scripts/**/*.js
config/**/*.js
!config/eslintrc/**/*.js
scripts/**/*.js
**/*.d.ts
**/*.d.mts
**/*.d.cts
!**/react-app-env.d.ts
!**/vite-env.d.ts
!**/globals.d.ts
Expand Down
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ yarn.lock
*.jpeg
*.xml
*.ico
*.d.ts
.firebaserc
hosting.YnVpbGQ.cache
LICENSE
Expand All @@ -37,6 +36,9 @@ packages/utils/syncflow/docs/**/*.js
.wireit
*.tsbuildinfo

packages/strict-ts-lib/source/unchanged
packages/strict-ts-lib/source/temp
!packages/strict-ts-lib/source/dist

# Optional eslint cache
.eslintcache
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
{
"mode": "auto"
}
]
],
"eslint.experimental.useFlatConfig": true
}
44 changes: 20 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ $ yarn ws:build
- `/packages` : メンテしているコード置き場。 package.json の存在するディレクトリはすべて workspace として扱われる。
- `/apps` : React などで作成されたアプリ
- `/utils` : TypeScript や React などで使うライブラリ
- `/slides` : reveal.js 製のスライド
- `/others``/tools` : その他ツール群(一部はメンテできていないものもあるのでそれらは `/experimental` に移動すべきかも…)
- `/experimental` : メンテナンス対象外のコード置き場
- package.json の内容について
- パッケージ名は原則 `@noshiro/` 始まりにしてある。
Expand All @@ -23,6 +25,7 @@ $ yarn ws:build
- 各 workspace の devDependencies は基本的に使用せず、ルートディレクトリの package.json にまとめて記述している。型定義を共有している都合で TypeScript のバージョンも monorepo 全体で統一している( `/experimental` 配下は除く)。
- npm scripts 定義
- 直接手動実行しない想定の内部コマンドには `z:` または `zz:` プレフィックスをつけて後ろにソートされるようにしている。
- commit 時の待ち時間削減のために husky hooks はあえて導入していない。代わりに GitHub Actions でチェックするようにしている。
- コマンド実行ツール
- npm-run-all
- 用途
Expand All @@ -40,30 +43,29 @@ $ yarn ws:build
- packages/utils に関しては repository 初期設定として予めビルドしておく運用を想定しており、 packages/apps 内の各コマンドで依存 utils の build を dependencies に加えることはしていない(記述が多くなるデメリットがあり、キャッシュされた結果とはいえ実行時間が伸びることによる不便さが大きいため)。
- TODO: `Wireit could not find the script name in the "npm_config_argv" environment variable. Arguments may not be interpreted correctly. See https://github.com/yarnpkg/yarn/issues/8905, and please consider upgrading to yarn 3.x or switching to npm.` という警告が出ているので yarn v3 に更新する。
- configs
- eslint
- 共通定義を `config/eslintrc/eslint-rules` に定義している。
- `plugin:@typescript-eslint:recommended` 等の public な config は使っておらず、 rule の設定を明示的に記述している。
- 主に多数の config を extends に追加した際のルール設定の上書き結果が曖昧になる問題を避けるため。各ルールはちょうど 1 回ずつ定義されている状態になっている。
- `@typescript-eslint` のルールに対応する `eslint` のルールや `prettier` と競合するルールを無効化する必要がある場合があるが、これらは適宜 plugin の提供している config を参考に手動で設定している。
- `prettier` と競合する eslint のスタイリング関係のルールを off にする設定は、 `eslint --fix` 結果と `prettier --write` 結果が競合していないことにより正しさを確認しているがそれ以上のことはしていない。
- このディレクトリ内の config には rule に option まで型が付き補完が効くようになっている。
- この型定義は各 eslint plugin の schema から `config/eslintrc/generate-rules-type` 内のスクリプトで自動生成(その後一部手動修正)している。
- `yarn gen-eslint-rules-type` により生成(その後一部手動修正が必要)
- この仕組みにより、 plugin アップデート時には上のコマンドを実行し git 差分を確認することで、追加・削除されたルールを発見できるようになっている。
- schema に deprecated フラグが設定されているルールの severity は `"off"` しか選べないような型を生成しているため、 deprecated になったルールが有効のままにはならないことを保証している(`type-check:root` で型チェックできる)。
- commit 時の待ち時間削減のために husky hooks はあえて導入していない。代わりに GitHub Actions でチェックするようにしている。
- 一部のルールは false positive が多いなどの理由で workspace ごとに個別に無効化していることがある。
- tsconfig
- 各 workspace で継承する共通 tsconfig 定義を置いている。
- `nolib` の付いた tsconfig は標準ライブラリをデフォルトで読み込まない設定になっている。代わりに各 workspace のルート index.ts などで `/// <reference path="../../../utils/stdlib/stdlib.d.ts" />` のように reference 文を入れてカスタム lib 型定義を読み込むようにしている。ほとんどの TypeScript project の workspace で nolib の tsconfig を使用している。
- `nolib` の付いた tsconfig は標準ライブラリをデフォルトで読み込まない設定になっている。代わりに各 workspace のルート index.ts などで `/// <reference types="@noshiro/stdlib" />` のように reference 文を入れてカスタム lib 型定義を読み込むようにしている。ほとんどの TypeScript project の workspace で nolib の tsconfig を使用している。
- `packages/utils/stdlib/stdlib.d.ts` の型定義は、TypeScript の標準 lib 型定義を元に半自動生成しており、一部の型を厳格化する目的で作成している(詳細は `packages/utils/stdlib` の script 等を参照)。
- 特殊 utility の説明
- `packages/utils/stdlib`
- `packages/utils/eslint-utils`
- eslint 共通設定を定義している。
- ESModule で記述するために flat config を導入(2023/11)
- TypeScript で記述している
- `yarn workspace @noshiro/eslint-utils build` により生成(その後一部手動修正が必要)
- `plugin:@typescript-eslint:recommended` 等の public な config は使っておらず、 rule の設定を明示的に記述している。
- 主に多数の config を extends に追加した際のルール設定の上書き結果が曖昧になる問題を避けるため。各ルールはちょうど 1 回ずつ定義されている状態になっている。
- `@typescript-eslint` のルールに対応する `eslint` のルールや `prettier` と競合するルール無効化が必要な場合があるが、これらは適宜 plugin の提供している config を参考に手動で設定している。
- `prettier` と競合する eslint のスタイリング関係のルールを off にする設定は、 `eslint --fix` 結果と `prettier --write` 結果が競合していないことにより正しさを確認しているがそれ以上のことはしていない。
- config には rule に option まで型が付き補完が効くようになっている。
- この型定義は各 eslint plugin の schema から `scripts` 内のスクリプトで自動生成(その後一部手動修正)している。
- この仕組みにより、 plugin アップデート時には上のコマンドを実行し git 差分を確認することで、追加・削除されたルールを発見できるようになっている。
- schema に deprecated フラグが設定されているルールの severity は `"off"` しか選べないような型を生成しているため、 deprecated になったルールが有効のままにはならないことを保証している。
- 一部のルールは false positive が多いなどの理由で workspace ごとに個別に無効化していることがある。
- `packages/strict-ts-lib`
- TypeScript の標準ライブラリの型を一部厳格化した型を提供するパッケージ。
- workspace のルート index.ts などで `/// <reference path="../../../utils/stdlib/stdlib.d.ts" />` のように reference 文を入れてこのカスタム lib 型定義を読み込ませる使い方ができる。標準ライブラリをオフにする必要があるため、 tsconfig.\*\*.nolib.json を併せて使う必要がある。
- `packages/utils/ts-type-utils`
- TypeScript 型ユーティリティ集。workspace 内で `DeepReadonly` などの型を使用できるようにする。
- `stdlib.d.ts` と同様 `/// <reference path="../../../utils/ts-type-utils/ts-type-utils.d.ts" />` のように reference 文を入れて読み込ませる。
- strict-ts-lib
- `packages/utils/global-*`
- `packages/apps` 内の各パッケージで使用。
- `global-X` は、 (P)React プロジェクトで頻繁に使うユーティリティを import 無しで使用できるようにするためのツール。 workspace に適切に設定すると `React.useMemo` などのユーティリティを import 無しで使えるようになる。
Expand Down Expand Up @@ -98,11 +100,5 @@ workflow は .github ディレクトリに定義されている。
- `main` : デフォルトブランチ
- `develop` : 開発用のブランチ
- `archive/*` : 作業中のコード置き場
- `deploy-rich-poll``packages/app/poll-discord-app` のデプロイトリガーにしているブランチ。
- `main` ブランチへの関係ない変更で Railway への無駄なデプロイが走らないようにするため。

### dependencies memo

- `@babel/preset-react`
- `vite-plugin-markdown` の依存だが別途 install が必要
- https://github.com/hmsk/vite-plugin-markdown/issues/447
4 changes: 2 additions & 2 deletions articles/take-full-advantage-of-typescript-eslint.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ eslint を使う際、 `eslint:recommended`, `plugin:@typescript-eslint/eslint-r

基本的に使用している plugin のほぼすべてのルールが有効(`error`)な設定にしており、より優先したい ESLint ルールと競合するものや、 TypeScript ・ prettier(フォーマッター)と機能が重複していて冗長なもの、その他自分のコーディングスタイルでは邪魔になる安全性やパフォーマンスをほぼ損なわないルール(TypeScript の `namespace` 禁止など)だけ無効化するという強めの設定をしています。ルールのオプションもなるべく厳格な設定にしています。

https://github.com/noshiro-pf/mono/tree/main/config/eslintrc
https://github.com/noshiro-pf/mono/blob/main/config/eslint

以前私が eslint 設定を recommended config よりもう少し強化したいと考え始めた時、config を組み合わせる eslint config 記述スタイルでは、設定が増えるにつれ

Expand All @@ -59,7 +59,7 @@ plugin ごとに全ルールを逐一設定していく作業が mono repo な
については、各ルールのオプションにまで個別に型が付いた config の型を各 plugin の json schema から自動生成することまでやっています。自動生成スクリプトも上のリンクに置いてあります [^generate-rules-type]。これをやってみて副産物として得られたメリットではありますが、 plugin のバージョンを上げたときに追加されたルールやオプション、あるルールが deprecated になったことなどにも気づきやすくなったのは良い点でした。

[^generate-rules-type]: `generate-rules-type` ディレクトリの [`main.mjs`](https://github.com/noshiro-pf/mono/blob/main/config/eslintrc/generate-rules-type/main.mjs) 中をよく読めば分かりますが、一部 `json-schema-to-typescript` による型生成が上手くいっていない箇所を後でアドホックに修正しているところがあったりもします。
[^generate-rules-type]: `generate-rules-type` ディレクトリの [`main.mjs`](https://github.com/noshiro-pf/mono/blob/main/config/eslint/generate-rules-type/main.mjs) 中をよく読めば分かりますが、一部 `json-schema-to-typescript` による型生成が上手くいっていない箇所を後でアドホックに修正しているところがあったりもします。

これらの実装についてもどこかで紹介しようと思っているのですが、今回は詳細は省きます。

Expand Down
31 changes: 22 additions & 9 deletions articles/typescript-type-utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,35 @@ expectType<number, string>('!=');
expectType<any, 1>('!=');
```

型が等価 or 部分型かどうか判定します
型の等価性や部分型関係をチェックするユーティリティです

- `expectType<A, B>("=")` は型 `A` と型 `B` が等価であるときに型エラーにならず、そうでないときに型エラーになります。
- `expectType<A, B>("<=")` は型 `A` が型 `B` の部分型であるときに型エラーにならず、そうでないときに型エラーになります
- `expectType<A, B>("!=")` は型 `A` と型 `B` が等価でないときに型エラーにならず、等価であるときに型エラーになります
- `expectType<A, B>("!<=")` は型 `A` が型 `B` の部分型でないときに型エラーにならず、部分型であるときに型エラーになります
- `expectType<A, B>("!=")` `"="` の逆です
- `expectType<A, B>("<=")` は型 `A` が型 `B` の部分型であるとき型エラーにならず、部分型でないときに型エラーになります
- `expectType<A, B>("~=")` `A` `B` の部分型かつ `B``A` の部分型であるときに型エラーにならず、そうでないときに型エラーになります。 `"="` の内部実装の `TypeEq<A, B>` は例えば `{ x: 1 } & { y: 2 }``{ x: 1; y: 2 }` を区別してしまう程厳密なものなので、もう少し緩い等価判定を行いたい場合に用意しています

--- 実装 ---

```ts
const expectType = <A, B>(
/**
* @param _relation `"=" | "~=" | "<=" | ">=" | "!<=" | "!>=" | "!="`
* @description
* - `expectType<A, B>("=")` passes if `A` is equal to `B`.
* - `expectType<A, B>("~=")` passes if `A` extends `B` and `B` extends `A`.
* - `expectType<A, B>("<=")` passes if `A` extends `B`.
* - `expectType<A, B>(">=")` passes if `B` extends `A`.
* - `expectType<A, B>("!<=")` passes if `A` doesn't extend `B`.
* - `expectType<A, B>("!>=")` passes if `B` doesn't extend `A`.
* - `expectType<A, B>("!=")` passes if `A` is not equal to `B`.
*/
export const expectType = <A, B>(
_relation: TypeEq<A, B> extends true
? '<=' | '='
: TypeExtends<A, B> extends true
? '!=' | '<='
: '!<=' | '!=',
? '<=' | '=' | '>=' | '~='
:
| '!='
| (TypeExtends<A, B> extends true
? '<=' | (TypeExtends<B, A> extends true ? '>=' | '~=' : '!>=')
: '!<=' | (TypeExtends<B, A> extends true ? '>=' : '!>=')),
): void => undefined;
```

Expand Down
43 changes: 0 additions & 43 deletions config/eslintrc/.eslintrc.base.js

This file was deleted.

Loading

0 comments on commit 2377f25

Please sign in to comment.