😺
TS Chalenges
Pick
type MyPick <T, K extends keyof T> = {[P in K] : T[P]}
type Person = {
Name: string,
Age: number
}
const person: MyPick<Person, "Name"> = {
Name: 'person'
}
補足
K : K extends keyof Tで、T型のkeyをユニオン型で取得する。
[P in K] : Mapped typesという。以下参照
Mapped types
type Exanple = {[P in 'NameFirst' | 'NameLast'] : string}
type Example = {NameFirst: string, NameLast: string}
Readonly
// Readonly
type MyReadonly<T> = {readonly [P in keyof T] : T[P]}
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
Object Tuple
type TupleToObject<T extends readonly string[]> = {[P in T[number]] : P}
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
type result = TupleToObject<typeof tuple>
// expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
Exclude
type MyExclude<T, K extends T> = T extends K ? never : T
type Result = MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'
// 以下のようになる。
// 'a' extend 'a' ? never : T → never
// 'b' extend 'a' ? never : T → 'b'
// 'c' extend 'a' ? never : T → 'c'
※ Distributive Conditional Types(分配的なConditional Types)
補足
type value = 3 // 3しか入らないリテラル型
type value = 3 | 4 | 5 // 3、4、5しか入らないユニオン型
Awaited
// Awaited
type MyAwaited<T extends Promise<any>> = T extends Promise<infer U> ? U extends Promise<any> ? Awaited<U> : U : never;
type MyAwaitedResult = MyAwaited<Promise<Promise<string>>>;
infer U: 型推論
Conditional Types( X extends Y ? L : R)のY以降に使えるキーワード
X extends Y<infer Z>においてX extends Y<any>を満たすとき、anyの部分にマッチする型を型変数Zに代入し、Lの部分で使えるようにする。
今回の場合、Promise<infer U>とすることで、Promiseのジェネリクス部分で定義されている型を推論できる。
If
type If<T extends boolean, K, U> = T extends true ? K : U
Parameter
const foo = (arg1: string, arg2: number): void => {}
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer U) => any ? U : never;
type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
参考文献
Discussion