工具类型实现
内置类型
Partial<T>
// example
interface Todo {
title: string;
description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
const todo1 = {
title: "organize desk",
description: "clear clutter"
};
const todo2 = updateTodo(todo1, {
description: "throw out trash"
});
// implement
type Partial<T> = {
[P in keyof T]?: T[P]
}
Required<T>
type Required<T> = {
[P in keyof T]-?: T[P]
}
Readonly<T>
type Readonly<T> = {
readonly [P in keyof T]: T[P]
}
Pick<T, K>
// example
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false
};
// implement
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
Omit<T, K>
// example
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo, "description">;
const todo: TodoPreview = {
title: "Clean room",
completed: false
};
// implement
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
// or
type Omit<T, K> = {
[P in Exclude<keyof T, K>]: T[P]
}
Extract<T, U>
type Extract<T, K> = T extends K ? T : never
Exclude<T, U>
// example
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number
// implement
// extends搭配 ?: 运算符使用
type Exclude<T, U> = T extends U ? never : T;
// 相当于: type A = 'a'
type A = Exclude<'x' | 'a', 'x' | 'y' | 'z'>
Record<K, T>
type Record<K extends keyof any, T> = {
[P in K]: T
}
NonNullable<T>
type NonNullable<T extends keyof any> = T extends null | undefined ? never : T
Parameters<T>
// infer 关键字
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
ReturnType<T>
// infer 关键字
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : never
ConstructorParameters<T>
type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
InstanceType<T>
type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
Awaited<T>
type MyAwaited<T> = T extends Promise<infer T> ? MyAwaited<T> : T;
其他
Uppercase
,全体大写Lowercase
,全体小些Capitalize
,首字母大写Uncapitalize
,首字母小写
Equal
非内置工具类型,用于比较两个类型完 全相等,因为其高泛用性和实现的特殊性所以特别拎出来讨论。社区主流的实现如下:
export type Equal<X, Y> =
(
(<T>() => (T extends X ? 1 : 2)) extends
(<T>() => (T extends Y ? 1 : 2))
)
? true
: false;
Type Challenge
开始做题
简单题
Tuple To Object
问题的本质是元祖如何转化为联合类型
type TupleToObject<T extends readonly any[]> = {
[k in T[number]]: k
}
First Of Array
type First<T extends any[]> = T extends [infer F, ...infer R] ? F : never;
Length Of Tuple
需要注意的是需要用readonly any[]
,否则元祖会走到never
分支
type Length<T> = T extends readonly any[] ? T['length'] : never;