TypeScriptのタプル型推論使って型を改善
by sisisin
自己紹介
株式会社オプト シニアエンジニア @sisisin(しめにゃん)
TypeScriptの型定義でよくみるやつ(RxJSのObservableの型定義より抜粋)
何かというと、可変長引数や配列を受け取ったときに、Array<T>のように一緒くたな型ではなく、それぞれの要素を区別して扱いたい、というケースです
TypeScriptの型定義ではこの例のように泥臭く可変長引数の1つずつに対して型付けしているケースが良く見られます
今回はこれを改善した(ようとしている*)という話をします
*諸般の事情でまだPR出してないので。。近いうち出します
参考にした資料
kgtkrさんの TypeScriptで型安全なobjectのpick関数を定義する(型パラメーターを単一のリテラル型に制限する方法)
TypeScript 3.0のExtracting and spreading parameter lists with tuplesで遊ぼう
uhyoさんのTypeScriptの型初級
この辺の記事をめっちゃ参照して今回の改善に至りました
この場を借りてお礼申し上げますthx!
どこの何を解決した?
どこの何を解決した?
参考までに、今回の改善した型を試せるようにTypeScript Playground上に サンプル を置いておきました
もしよければ御覧ください
before
解説
第一引数(stateGetters): StateGetter<T>のタプル
第二引数(mapper): コールバック関数。コールバック関数の引数のn番目が、第一引数のn番目のTとなる
例えば `useMappedState([sg1,sg2], (s1, s2) => {})` という記述をした場合、
という具合です
解説
元の実装では、この `stateGetters` という `StateGetter<T>` のタプルの型を、要素の数に対応する分だけで定義していました
のようなイメージ(実際のコードはリンクから見てもらえればと)
after
after解説
関数の第一引数 `stateGetters: T` について:
after解説
第二引数 `mapper` について
大変読みにくいのですが、単純化すると、 `mapper: (...args: ComplexType) => R;` です
after解説
この `ComplexType` がなにかというと、先程解説した「コールバック関数の引数のn番目が、第一引数のn番目のTとなる」に該当する表現です
`stateGetters: T` の `T` を元にして、この `mapper` 関数の引数の型を推論させる、というものになります
詳しい記法については端折りますが、 `StateGetter<X>[]` に所属する型を元に、タプルの要素一つ一つに対して、`X` を抽出する、という事を書いています
after(再掲)
何が嬉しいの?
というわけで、ライブラリの型をタプル型推論を利用して改善したという話でした
Happy Hacking!