Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

develop #630

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
85ddbab
docs: update Zenn articles
noshiro-pf Feb 3, 2025
e73a4ed
create playground implement-react-hooks
noshiro-pf Feb 11, 2025
840b9c0
--------
noshiro-pf Oct 10, 2022
02a9a31
--------
noshiro-pf Jan 9, 2023
002472f
--------
noshiro-pf Oct 9, 2022
21493c8
feat: [event-schedule-app] sort event list of user by create time
noshiro-pf Jan 30, 2025
c988055
--------
noshiro-pf Oct 9, 2022
ea1a1be
--------
noshiro-pf Oct 9, 2022
5726142
improve branded type implementation [WIP]
noshiro-pf Feb 6, 2025
c6caf13
Revert "improve branded type implementation [WIP]"
noshiro-pf Feb 6, 2025
cc84bcd
--------
noshiro-pf Jan 9, 2023
5ed462f
feat: ts-utils: add Num.add [WIP]
noshiro-pf Oct 1, 2023
1036e63
--------
noshiro-pf Oct 9, 2022
2b66d2f
feat: [event-schedule-app] archiveAll
noshiro-pf Jan 30, 2025
5f3c0a9
feat: [event-schedule-app] add createdAt, updatedAt [WIP]
noshiro-pf Jan 31, 2025
395b821
--------
noshiro-pf Jan 9, 2023
bb73a2f
refactor: [eslint-config] add RuleSeverityWithDefaultOption type
noshiro-pf Feb 9, 2025
a14bc58
chore: update eslint rule settings
noshiro-pf Feb 11, 2025
7d884d0
fix: [eslint-configs] fix gen-rules-type command
noshiro-pf Feb 22, 2025
11cd781
fix: [eslint-configs] support DeprecatedInfo
noshiro-pf Feb 22, 2025
54a8dbd
feat: [eslint-configs] add eslint-plugin-react-perf and update packages
noshiro-pf Feb 22, 2025
cff946e
chore: [eslint-configs] remove category from JSDoc
noshiro-pf Feb 22, 2025
bfb4167
refactor: fix eslint errors
noshiro-pf Feb 22, 2025
fa53506
--------
noshiro-pf Oct 10, 2022
c1ae433
feat: sort eventList by createdAtMillis in frontend
noshiro-pf Mar 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions articles/biome-vs-eslint-prettier-2025.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: 'ESLint, prettier の代替として見たときの Biome についての感想メモ'
emoji: '🐈'
type: 'tech' # tech: 技術記事 / idea: アイデア
topics: ['biome', 'eslint', 'prettier', 'typescript']
published: false
---

## Biome のメリット(ユーザー目線)

- 速度:
- BiomeはRustで書かれており、非常に高速に動作する。
- 統合性:
- Biome は、リンター、フォーマッター、そして将来的にコンパイラなど、複数の機能を統合している。これにより、ツール間の互換性問題を減らし、開発体験を向上させることができる。
- 設定の簡素化:
- Biome は、デフォルト設定が優れており、多くのプロジェクトで追加設定なしに利用できる。
- biome.json でlint ルール等に補完が効くため記述体験が良い。
- より厳密な構文解析:
- BiomeのパーサはPrettierのパーサよりも厳密に構文を解析する。そのため、より正確にエラーを検出し、コードを整形できる
- ESLint, prettier との比較
- 後発であるため prettier や ESLint の色々な問題を解決しており将来性がある

prettier plugin recommended config などを超えて ESLint の rule option をがっつり定義したものと比べると(開発思想上納得できるものの)カスタマイズできる余地が少なく機能が現状まだ劣るので使いづらい。

## 執筆時点(2025年2月24日)時点での筆者の結論

ESLint + prettier の方がコードの品質を保つ事に関しては現状 Biome より高機能であるため、当分は実行が遅くても ESLint + prettier を使うことになりそうです。
以前 [ESLint を使い倒す(おすすめルール紹介)](https://zenn.dev/noshiro_piko/articles/take-full-advantage-of-typescript-eslint) という記事で様々な ESLint ルールを紹介しましたが、これらの中には Biome にはまだ実装されていないものや設定が現状多く存在します。既に主要な ESLint plugin から移植済みの lint ルールであっても option が削られているケースも確認しており(どれだったか思い出したら書き足します🙇)、もしかしたらこれが意図的な場合一部の option は今後も追加されないかもしれません。

Biome の基本設定で足りないところを、重複しないように特定のルール設定だけ ON にした ESLint と prettier を併用して補う、という使い方も一応可能ではありますが、ツールの統合・設定の簡素化というメリットはむしろ確実に悪化してしまう上に速度面で得をするのかすら怪しいため、あまり得策とは言えないと思われます。
752 changes: 752 additions & 0 deletions articles/frontend-frameworks-survey.md

Large diffs are not rendered by default.

Binary file added articles/frontend-frameworks/benchmark1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added articles/frontend-frameworks/benchmark2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added articles/frontend-frameworks/virtual-dom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion articles/take-full-advantage-of-typescript-eslint.md
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ JavaScript の `Array.prototype.sort` はデフォルトで文字列比較によ
```

この ESLint ルールを有効にすると `.sort()` の引数を省略できないようになります。
文字列の配列に関しては比較関数省略時のデフォルト動作が自然であり採用したい場合が多いので、 `ignoreStringArrays` option も有効にしておくのが有効です
文字列の配列に関しては比較関数省略時のデフォルト動作が自然であり採用したい場合が多いので、 `ignoreStringArrays` option も有効にしておくと便利です

```json
{
Expand Down
136 changes: 67 additions & 69 deletions articles/typescript-branded-type-int.md

Large diffs are not rendered by default.

229 changes: 145 additions & 84 deletions articles/typescript-range-type.md

Large diffs are not rendered by default.

54 changes: 27 additions & 27 deletions articles/typescript-type-level-min.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: 'TypeScript の型ユーティリティ Min, Max の実装'
title: '[型パズル]TypeScript の型ユーティリティ Min, Max の実装'
emoji: '🐈'
type: 'tech' # tech: 技術記事 / idea: アイデア
topics: ['typescript']
topics: ['typescript', 'type-challenges']
published: true
---

Expand All @@ -15,21 +15,21 @@ published: true
type Min<N extends number> = /* TODO */;
type Max<N extends number> = /* TODO */;

type R1 = Max<1 | 2 | 3>; // 3
type R2 = Min<1 | 2 | 3>; // 1
type T1 = Max<1 | 2 | 3>; // 3
type T2 = Min<1 | 2 | 3>; // 1
```

## Min の実装

`Min<N>` は以下のコードで実装できます。

```ts
type _MinImpl<
type Min<N extends number> = MinImpl<N, []>;

type MinImpl<
N extends number,
T extends readonly unknown[],
> = T['length'] extends N ? T['length'] : _MinImpl<N, [0, ...T]>;

export type Min<N extends number> = _MinImpl<N, []>;
> = T['length'] extends N ? T['length'] : MinImpl<N, [0, ...T]>;
```

(簡単な解説)
Expand All @@ -39,9 +39,9 @@ TypeScript の型レベルプログラミングで非負整数に関する処理

```
Min<1 | 2 | 3>
-> _MinImpl<1 | 2 | 3, []>
-> _MinImpl<1 | 2 | 3, [0]> // T["length"] (= 0) extends 1 | 2 | 3 は false なので再帰
-> 1 // T["length"] (= 1) extends 1 | 2 | 3 は true なので [0]["length"] = 1 を返す
-> MinImpl<1 | 2 | 3, []>
-> MinImpl<1 | 2 | 3, [0]> // T["length"] (= 0) extends 1 | 2 | 3 は false なので再帰
-> 1 // T["length"] (= 1) extends 1 | 2 | 3 は true なので [0]["length"] = 1 を返す
```

## Max の実装
Expand All @@ -50,12 +50,12 @@ Min<1 | 2 | 3>

<!-- prettier-ignore -->
```ts
type _MaxImpl<N extends number, T extends readonly unknown[]>
export type Max<N extends number> = MaxImpl<N, []>;

type MaxImpl<N extends number, T extends readonly unknown[]>
= [N] extends [Partial<T>["length"]]
? T["length"]
: _MaxImpl<N, [0, ...T]>;

export type Max<N extends number> = _MaxImpl<N, []>;
: MaxImpl<N, [0, ...T]>;
```

https://www.typescriptlang.org/play?#code/FAFwngDgpgBA+gWQIYA8CSBbCAbAPAORihRCgDsATAZxjIFcMAjKAJwBoYAVIk86mFlCQUA9mWxgYdMgGsyIgO5kA2gF0YAXhhqAfJu351xUpRrKACkhYgAlkjycdygETZyAcxAALZ6vUB+Lhc3Mk8fdQAueGR0LDx8DmUABg4AOnTOVR1gYGIIEWsYcGgYGIIeE356JlY9LURUTBwCHQBuHOLYACUoKjpsEH1lYBhS1FwknTYRsZQJmAAfGABGRZgAJimZsvW1gBY1gDYt0eSOFJgLpNVgj29fadHLazs8M8vz86zb0PvVYH+wCAA
Expand All @@ -82,26 +82,26 @@ type Index = Partial<[0, 0, 0, 0]>['length'];

```
Max<1 | 2 | 3>
-> _MaxImpl<1 | 2 | 3, []>
-> _MaxImpl<1 | 2 | 3, [0]> // [1 | 2 | 3] extends [Partial<[]>["length"]] (= [0]) は false なので再帰
-> _MaxImpl<1 | 2 | 3, [0, 0]> // [1 | 2 | 3] extends [Partial<[0]>["length"]] (= [0 | 1]) は false なので再帰
-> _MaxImpl<1 | 2 | 3, [0, 0, 0]> // [1 | 2 | 3] extends [Partial<[0, 0]>["length"]] (= [0 | 1 | 2]) は false なので再帰
-> 3 // [1 | 2 | 3] extends [Partial<[0, 0, 0]>["length"]] (= [0 | 1 | 2 | 3]) は true なので [0, 0, 0]["length"] を返す
-> MaxImpl<1 | 2 | 3, []>
-> MaxImpl<1 | 2 | 3, [0]> // [1 | 2 | 3] extends [Partial<[]>["length"]] (= [0]) は false なので再帰
-> MaxImpl<1 | 2 | 3, [0, 0]> // [1 | 2 | 3] extends [Partial<[0]>["length"]] (= [0 | 1]) は false なので再帰
-> MaxImpl<1 | 2 | 3, [0, 0, 0]> // [1 | 2 | 3] extends [Partial<[0, 0]>["length"]] (= [0 | 1 | 2]) は false なので再帰
-> 3 // [1 | 2 | 3] extends [Partial<[0, 0, 0]>["length"]] (= [0 | 1 | 2 | 3]) は true なので [0, 0, 0]["length"] を返す
```

補足ですが、 `[N] extends [Partial<T>["length"]]` のところは "union distribution" という挙動を回避するために TypeScript の型レベルプログラミングでたびたび用いられるテクニックが使われています。
`extends` の両辺を配列にくるまず `N extends Partial<T>["length"]` としてしまうと、 `N` (例では `1 | 2 | 3`)が分配されてそれぞれ評価されてしまいます。 `[N]` `N[]` とすることでこの挙動を回避して union 型 `N` の全体と `Partial<T>["length"]` を直接比較することができます
`extends` の両辺を配列にくるまず `N extends Partial<T>["length"]` としてしまうと、 `N` (例では `1 | 2 | 3`)が分配されてそれぞれ評価されてしまいます。 `[N]` または `N[]` とすることでこの挙動を回避して union 型 `N` の全体と `Partial<T>["length"]` をそのまま比較することができます
逆に union 型の各要素についてループ処理を書きたいときには `N extends N ? ... : never` のようにして union distribution を使うこともあります。

ちなみに、先ほど載せたリンクの [StackOverflow の記事](https://stackoverflow.com/questions/62968955/how-to-implement-a-type-level-max-function-over-a-union-of-literals-in-typescri)では同じ投稿者が再帰上限にひっかからないための実装の改良も載せていますが、元実装

```ts
type _MaxImpl<N extends number, T extends any[]> = {
type MaxImpl<N extends number, T extends any[]> = {
b: T['length'];
r: _MaxImpl<N, [0, ...T]>;
r: MaxImpl<N, [0, ...T]>;
}[[N] extends [Partial<T>['length']] ? 'b' : 'r'];

export type Max<N extends number> = _MaxImpl<N, []>;
export type Max<N extends number> = MaxImpl<N, []>;

type Result = Max<1 | 2 | 512>;
// Type instantiation is excessively deep and possibly infinite. ts(2589)
Expand All @@ -111,12 +111,12 @@ type Result = Max<1 | 2 | 512>;

<!-- prettier-ignore -->
```ts
type _MaxImpl<N extends number, T extends readonly unknown[]>
type MaxImpl<N extends number, T extends readonly unknown[]>
= [N] extends [Partial<T>["length"]]
? T["length"]
: _MaxImpl<N, [0, ...T]>;
: MaxImpl<N, [0, ...T]>;

export type Max<N extends number> = _MaxImpl<N, []>;
export type Max<N extends number> = MaxImpl<N, []>;

type Result1 = Max<1 | 2 | 512>; // ok
type Result2 = Max<1 | 2 | 1024>; // Type instantiation is excessively deep and possibly infinite. ts(2589)
Expand Down
Loading
Loading