这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
0、前言
每天花几分钟练练ts...
1、获取函数返回类型
使用条件类型推断,利用infer声明返回的类型,T和Type是传入的函数,
type MyReturnType<T> = T extends (...args: any[]) => infer G ? G : never
// 源码
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
2、实现 Omit
Omit 会创建一个省略 K 中字段的 T 对象。
type MyOmit<T, K extends keyof T> = {
[P in Exclude<keyof T, K>]: T[P]
}
// 源码
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
3、Readonly 2
type MyReadonly2<T, K extends (keyof T) = keyof T> = Omit<T, K> & {readonly [id in K]: T[id] }
type MyReadonly2<T, K extends keyof T = keyof T> = Readonly<Pick<T, K>> & Omit<T, K>
type MyReadonly2<T, K = keyof T> = {
readonly [P in keyof T as P extends K ? P : never]: T[P]
} & {
[P in keyof T as P extends K ? never: P]: T[P]
}
type MyReadonly2<T, K> = { [Q in Exclude<keyof T, K>]: T[Q] } & {
readonly [P in Extract<keyof T, K>]: T[P];
};
4、深度 Readonly
它将对象的每个参数及其子对象递归地设为只读
type DeepReadonly<T extends Record<string, any>> = T extends Function
? T
: T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> } : T;
----
type DeepReadonly<T extends Object> = {
readonly [P in keyof T]: keyof T[P] extends never ? T[P] : DeepReadonly<T[P]>
}
----
type DeepReadonly<T> = {
readonly [P in keyof T]: keyof T[P] extends never ? T[P] : DeepReadonly<T[P]>
}
----
type IsArray = T extends Array ? true : false;
type IsFunction = T extends Function ? true : false;
type IsObject = T extends { [key: string]: any } ? IsFunction extends true ? false : true : false;
type NeedRecursive = IsArray extends true ? true : IsObject extends true ? true : false;
type DeepReadonly = {
readonly [key in keyof T]: NeedRecursive<T[key]> extends true ? DeepReadonly<T[key]>: T[key]
}
5、元组转合集
type TupleToUnion<T extends unknown[]> = T[number]
----
type TupleToUnion<T extends any[]> = T[number]
type arr = [123, '456', true]
type a = arr[number] // arr[number] 返回得到一个 union 类型 true | 123 | "456"
测试:
type Arr = ["1", "2", "3"];
type TupleToUnion<T extends unknown[]> = T[number]
type e = TupleToUnion<Arr>;
// 相当于
type e = "1" | "2" | "3"
type Chainable<T = {}> = {
option<K extends string, V = any>(key: K extends keyof T ? never : K, value: V): Chainable<T & { [O in K]: V }>
get(): T
}
6、可串联构造器
declare const config: Chainable
const result = config
.option('foo', 123)
.option('name', 'type-challenges')
.option('bar', { value: 'Hello World' })
.get()
// 期望 result 的类型是:
interface Result {
foo: number
name: string
bar: {
value: string
}
}
type Merge<T, U> = {
[P in Exclude<keyof T, keyof U>]: T[P]
} & {
[G in keyof U]: U[G]
}
type Chainable<T = {}> = {
option<K extends string, V>(key: K, value: V): Chainable<Merge<T, {[P in K]: V}>>
get(): T
}
7、Last of Array
实现一个通用Last<T>,它接受一个数组T并返回其最后一个元素的类型。
例如
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]
type tail1 = Last<arr1> // expected to be 'c'
type tail2 = Last<arr2> // expected to be 1
实现
type arr1 = ["a", "b", "c"];
// infer 关键字声明了一个新的类型变量B
type Last<T extends any[]> = T extends [...infer A, infer B] ? B : never;
// 或者
type Last<T extends any[]> = T extends [...any, infer L] ? L : never;
// 或者
type Last<T extends any[]> = [any, ...T][T["length"]];
type Res = Last<arr1>;
// 相当于 type Res = "c";
8、出堆
实现一个通用Pop,接受一个数组T并返回一个没有最后一个元素的数组。
type arr1 = ["a", "b", "c"];
type Pop<T extends any[]> = T extends [...infer U, any] ? U : never
type Res = Pop<arr1>;
// 相当于
type Res = ["a", "b"]