Object.groupBy の結果を Object.entries すると型に undefined が混ざる
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ groupBy すると結果に Partial がつく
◆ それを Object.entries すると value 側に undefined の可能性ありになる
◆ それを Object.entries すると value 側に undefined の可能性ありになる
Object.groupBy の型定義
TypeScript 寄りな話ですが一応書いてるのは JavaScript ですVSCode でコードを書いてると JavaScript でもマウスを乗せたときに組み込みの型や関数やそれらで処理した結果なら型の情報が表示されます
それを見ていて気になったのですが groupBy を通したときに型がおかしい気がします
まず groupBy ですが 配列とその配列の要素からキーに変換する関数を渡して配列をグループに分けてくれるものです
const group = Object.groupBy([1, 2, 3, 4, 5], n => n % 2)
// {
// 0: [2, 4]
// 1: [1, 3, 5]
// }
配列が空なら空のオブジェクトが結果です
キーがあればかならず 1 つ以上の要素が入った配列がバリューとしてあります
これをそれぞれの key/value に対して処理するために Object.entries で配列化して for-of で処理します
const group = Object.groupBy([1, 2, 3, 4, 5], n => n % 2)
for (const [key, items] of Object.entries(group)) {
console.log(key, items)
}
このときに items の型が
const items: number[] | undefined
になっていました
ここに undefined は来ないと思うのですけど
気になったので他の場所も型を表示させると
const group: Partial<Record<number, number[]>>
const entries: [string, number[] | undefined][]
Partial があるので undefined が生まれてそうです
Partial の必要なさそうですが たぶんこういうケースを考えてそうです
const group = Object.groupBy([1, 2, 3, 4, 5], n => n % 2 ? "foo" : "bar")
const group: Partial<Record<"foo" | "bar", number[]>>
とはいえ 多くの場合はグループのキーは任意の数値か文字列になってそうですし 来るはずのない undefined が出てくるのはどうなのかとおもいますけどね
型チェックしない JavaScript で書いてるので気にしてなかったですが TypeScript だと for-of の中で items が undefined でないことを assert したり手間が必要そうです
ちなみに VSCode 1.87 では groupBy は認識されてなくて型は any でした
アップデートして 1.88 になってから型が表示されるようなってました
同梱される TypeScript のバージョンが上がったようです
導入されたばかりということを考えるとバグという可能性もありそうです
やっぱり TypeScript の型定義反映は遅い
この件で やっと TypeScript でも groupBy が対応したんだと思って それなら他も対応したのかなと 以前 TypeScript を触ることがあったときに使えず不便に感じたものも見てみました具体的には Promise の追加メソッドと Iterator Helpers と Set の追加メソッドです
結果 Promise.withResolvers は対応していて 残りはどちらも未対応でした
Set のメソッドの Stage4 化は先週の TC39 ミーティングなので Stage4 に到達してから作業を始めるなら妥当なのかもしれませんが 設定に ES2020 みたいなバージョン以外に ESNext というのがあるのでいずれかのブラウザで実装された時点で対応しておいてほしいですね
Node.js も遅い
最近 JavaScript で関数系の追加が多かったこともあって Node.js の LTS だとこれらが使えなくて不便ですLTS の更新は 1 年に一回のペースですし マイナーバージョンアップで V8 バージョンって更新されないのですよね
Node.js だけなら諦めて新機能は使わないともできますが ブラウザと共有するモジュールだと ブラウザで使う部分でも新しい機能が使えません
またテストを実行するときも基本 Node.js で動かすので テストが動かなかったりします
テストという本来の処理には不要なもののせいで コードを変更するのはとても避けたいことなので 不満が強いのですよね
Deno だとどうなのかなと思って見てみると パッチバージョンアップデートで V8 バージョンが更新されてるようでした
TypeScript の方はマイナーバージョンアップデートで更新されてるようです
[root@d2de92b52c19 /]# proto run deno 1.41.0 -- --version
deno 1.41.0 (release, x86_64-unknown-linux-gnu)
v8 12.1.285.27
typescript 5.3.3
[root@d2de92b52c19 /]# proto run deno 1.41 -- --version
deno 1.41.3 (release, x86_64-unknown-linux-gnu)
v8 12.3.219.9
typescript 5.3.3
[root@d2de92b52c19 /]# proto run deno 1.42.0 -- --version
deno 1.42.0 (release, x86_64-unknown-linux-gnu)
v8 12.3.219.9
typescript 5.4.3
[root@d2de92b52c19 /]# proto run deno 1.42 -- --version
deno 1.42.4 (release, x86_64-unknown-linux-gnu)
v8 12.3.219.9
typescript 5.4.3
ブラウザにバージョンが近いだけでも助かるので フロントエンドの JavaScript のテストの実行は Deno で良いような気がしてきました
ただ Jest や Vitest みたいな高機能テストツールって Deno でも動くのでしょうか