配列から配列への型レベルmap
配列を取って、計算して、配列を返す型
hsのような言語で考えるなら、再帰関数を想像するがぜんぜん異なる

TSの難しいポイントの1つだと思う
イディオムとして頭に入っていないと使えない
[a,b,c]
→ [f a, f b, f c]
と変換する
こんなふうに書く
tstype Hoge<XS extends unknown[]> = {
[K in keyof XS]: F<XS[K]>;
};
F
は何かしらの、適用したい型関数
この
[P in keyof T]: ..
というイディオムは、recordに対して使われているのはよく見る

例えば、 Partial
とか Required
とか Readonly
とか
これを配列に使う
例
number
の配列を、 string
の配列に変換する
tstype Nums2Strs<T extends number[]> = {
[K in keyof T]: Num2Str<T[K]>;
};
// 関数
type Num2Str<N> = N extends number ? `${N}` : never;
// 結果
type Hoge = Nums2Strs<[1, 2, 3, 4]>; // ['1', '2', '3', '4']
例
型関数の重ね具合に依って、普通に書くとerrorになるケースが存在する
tstype Box<V = unknown> = { value: V };
type Unbox<B extends Box> = B['value'];
type UnboxAll<T extends Box[]> = {
// [I in keyof T]: Unbox<T[I]>; // こう書きたいが書けない
[I in keyof T]: Unbox<Extract<T[I], T[number]>>; // しゃーなし、こう書く
};
type B = [Box<'a'>, Box<'b'>, Box<'c'>];
type C = UnboxAll<B>; // ['a', 'b','c']
ちなみに、 Map<F, XS>
のような高階型関数は定義できない
高階多相型がないので
型引数 F
は、何かしらの型関数であって欲しいが、それが定義できない
頑張る方法はあるっぽい