2022/07/14
2022/07/14
こんにちは、@yamakenjiです。
今回は、type-challengeをちゃんとやっていきます
全133問のうち、easyの13問に着手(本当に簡単なのかな?)
TS 標準のPick<T, K>
を自前で実装する
いきなり Mapped Types や keyof 等をうまく活用していく必要がある
type MyPick<T, K extends keyof T> = {
[key in K]: T[key];
};
TS 標準のReadonly<T>
を自前で実装する
各プロパティに対して、readonly をつけるだけ プロパティの抽出は Pick と同様
type MyReadonly<T> = {
readonly [key in keyof T]: T[key];
};
MyPick や Readonly と同じように実装する
const a = ['a', 'b'] as const
のようにタプルできた場合、
typeof で肩を取って、T[number]とするとリテラル型がとれる
type TupleToObject<T extends readonly any[]> = {
[key in T[number]]: key;
};
配列の最初の型を返すジェネリック型 First を実装する
これは、TS(2.8 以降)の Conditional Types を利用する
T extends U ? X : Y とすることで、U が T の部分型であれば X、そうでなければ Y とする
下記では、空配列の場合は never、それ以外は配列の最初の型を返している
type First<T extends any[]> = T extends [] ? never : T[0];
与えられたタプルの長さを返す型 Length を実装する
これは、Indexed Access Types を利用する
例えば、T が配列型なのであれば、T[U]
とすることで、U にそのメソッドを入れることができる
type Length<T extends readonly any[]> = T['length'];
TS 標準の Exclude を実装する
Conditional Types を利用する
Conditional Types は、型引数にユニオン型が与えられた場合、それぞれ反復して処理を行う
ユニオン型である T を反復して U の部分型であるかを確認する
ここでは、U が T の部分型なら never, そうでないならそのまま型を返す
type MyExclude<T, U> = T extends U ? never : T
PromiseでWrapされている型を抽出する
inferを利用し、型を利用する時に代入した型を推論して利用する
Promise<any>を受け取った上で、実際に評価するときにinfer Pで推論する
type MyAwaited<T> = T extends Promise<infer P> ? P extends Promise<any> ? MyAwaited<P> : P : error;
Conditional Typesを利用する
type If<C extends boolean, T, F> = C extends true ? T : F;
配列のスプレッド構文を型で行う
type Concat<T extends any[], U extends any[]> = [...T, ...U]
inferを利用し、再起的に配列に部分型であるかを確認する
[infer First, ...infer rest] で、配列の最初の型をTに抽出、配列全体を再起的に確認する
type Includes<T extends readonly any[], U> = T extends [infer First, ...infer rest] ? (
Equal<First, U> extends true ? true : Includes<rest, U>
) : false
Concatと同じように、スプレッド構文等で追加していく
type Push<T extends any[], U> = [...T, U]
ConcatやPushと同等
type Unshift<T extends any[], U> = [U, ...T]
Parametersはある関数型T引数の型をタプルとして取得する組み込み型
(...args):any[] => any
からParametersに渡したときに引数を取得できれば良い
inferを用いていく
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never