Type challenges
キホンのキ
こちらの記事が参考になる
Narrowing
型引数に対してextends
を使うと、受け取れる型を狭めることができる
// valueはstringかnumberのどちらかしか受け取れない
type Sample<T extends string | number> = { value: T };
Conditional Types / 条件付き型
extends
を右辺で使うことで、もし T が U なら X,そうでなければ Y を返す、というような処理ができるT extends U ? X : Y
Distributive Conditional Types / ユニオン型の分配法則
- Conditional Types の T が Union 型だった場合には、総当りで処理され、結果が再びユニオンとして結合される
never
- Conditional Types と併用して、型を返したくない時に使う
Distributive Conditional Types と never を使うと、以下のようなことができる
type MyExclude<T, U> = T extends U ? never : T;
type Sample = MyExclude<
string | number | bigint | object | boolean | Function,
number | boolean
>;
// => string | bigint | object | Function
infer
- Conditional Types 内で型変数を抽出できる
- 型引数(
<>
)が与えられてが計算が完了している型から、もとの型変数を取り出すのに使える
type ExtractType<T> = T extends Array<infer U> ? U : never;
type Sample = ExtractType<Array<string>>; // string
Map Types
- 既存の型を操作し新しい型を生成する機能
- 既存の型の各プロパティを変更、追加、削除できる
type Person = {
name: string;
age: number;
};
// すべてのプロパティをオプショナルにする
type PartialPerson = {
[K in keyof Person]?: Person[K];
};
その他
-
SomeArr[number]
で、配列型を Union 型に変換できるtype List = (string | number | boolean)[];
// - string | number | boolean になる
// - 配列が持ちうる全ての型を、Union型にまとめる感じ
type Elem = List[number];
--- Challenges - Easy ---
Pick
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Readonly
interface Todo {
title: string;
description: string;
}
const todo: MyReadonly<Todo> = {
title: 'Hey',
description: 'foobar',
};
type MyReadonly<T> = {
readonly [P in keyof T]: T[P];
};
Tuple to object
// as const の表記が重要。
// - これがあるから、typeof tuple は ['tesla', 'model 3', 'model X', 'model Y'] という配列型になる
// - これがないと、typeof tuple はただのstring[]になる
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const;
// expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
const result: TupleToObject<typeof tuple>;
type TupleToObject<T extends readonly string[]> = {
[P in T[number]]: P;
};
First of Array
type arr1 = ['a', 'b', 'c'];
type arr2 = [3, 2, 1];
type head1 = First<arr1>; // expected to be 'a'
type head2 = First<arr2>; // expected to be 3
type First<T extends any[]> = T extends [] ? never : T[0];
Length of Tuple
type tesla = ['tesla', 'model 3', 'model X', 'model Y'];
type spaceX = [
'FALCON 9',
'FALCON HEAVY',
'DRAGON',
'STARSHIP',
'HUMAN SPACEFLIGHT',
];
type teslaLength = Length<tesla>; // expected 4
type spaceXLength = Length<spaceX>; // expected 5
type Length<T extends any[]> = T['length'];