Picktype MyPick<T, U extends keyof T> = {
[P in U]: T[P]
}
Readonlytype MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
Tuple to Objecttype TupleToObject<T extends ReadonlyArray<string | number>> = {
[P in T[number]]: P
}
First 取数组的第一个元素
type First<T extends unknown[]> = T extends [infer P, ...unknown[]] ? P : never
Array length取数组的长度
type Length<T extends ReadonlyArray<unknown>> = T['length']
Exclude type MyExclude<T, U> = T extends U ? never : T
Awaited 假如我们有一个
Promise对象,这个Promise对象会返回一个类型。在 TS 中,我们用Promise中的T来描述这个Promise返回的类型。请你实现一个类型,可以获取这个类型。比如:
Promise<ExampleType>,请返回ExampleType类型。
type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer P>
? (P extends Promise<unknown> ? MyAwaited<P> : P)
: never
先用条件推断,泛型T是否是
Promise返回,并用infer P指代返回值。
P有两种情况:
- 普通返回值类型
Promise类型
如果
P是Promise类型,则需要递归检查。对应的代码是:
P extends Promise<unknown> ? MyAwaited<P> : P如果是普通返回值类型,则直接返回
P。
为什么要加extends Promise<unknown>?
MyAwaited<T extends Promise<unknown>>的含义,是为了避免用户传入非Promise function。
如果用户违反规则,TypeScript会按报错处理。
Iftype If<C extends boolean, T, F> = C extends true ? T : F
Concat type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
Includestype Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false
// 逐个递归取出 Equal 比较
type Includes<T extends ReadonlyArray<any>, U> = T extends [infer R, ... infer K]
? (Equal<U, R> extends true ? true : Includes<K, U>)
: false
// 循环比较
type Includes<T extends ReadonlyArray<any>, U> = {
[K in keyof T]: Equal<U, T[K]>
}[number] extends false ? false : true
Pushtype Push<T extends unknown[], U> = [...T, U]
Unshift type Unshift<T extends unknown[], U> = [U, ...T]
Parameters
ts内置Parameters获取函数参数 转为 元组
type MyParameters<T extends (...args: any[]) => any> = T extends ((...args: infer P) => any) ? P : never
ReturnType
ts内置ReturnType获取函数返回值类型
type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer P ? P : never
Omit
ts内置Omit
type MyOmit<T, K extends keyof T> = {
[P in Exclude<keyof T, K>]: T[P]
}
使用
Exclude排除keyof T中的K类型
Readonly 2实现一个通用
MyReadonly2<T, K>,它带有两种类型的参数T和K。
K指定应设置为Readonly的T的属性集。如果未提供K,则应使所有属性都变为只读,就像普通的Readonly<T>一样
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in K]: T[P]
} & Omit<T, K>
DeepReadonly实现一个通用的
DeepReadonly<T>,它将对象的每个参数及其子对象递归地设为只读。
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] : (T[P] extends {} ? DeepReadonly<T[P]> : T[P])
}
From vue3 完美实现
type Primitive = string | number | boolean | bigint | symbol | undefined | null
type Builtin = Primitive | Function | Date | Error | RegExp
type DeepReadonly<T> = T extends Builtin
? T
: T extends Map<infer K, infer V>
? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends ReadonlyMap<infer K, infer V>
? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends WeakMap<infer K, infer V>
? WeakMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends Set<infer U>
? ReadonlySet<DeepReadonly<U>>
: T extends ReadonlySet<infer U>
? ReadonlySet<DeepReadonly<U>>
: T extends WeakSet<infer U>
? WeakSet<DeepReadonly<U>>
: T extends Promise<infer U>
? Promise<DeepReadonly<U>>
: T extends {}
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: Readonly<T>
Tuple to Uniontype TupleToUnion<T extends ReadonlyArray<unknown>> = T[number]