Partial => MyPartial
1.所有的变成可选
2.keyof主要核心转化联合类型,进行+?
type Foo = {
a: string
b: number
c: boolean
}
const a: MyPartial<Foo> = {}
const b: MyPartial<Foo> = {
a: 'aaaaa'
}
const c: MyPartial<Foo> = {
b: 123
}
const d: MyPartial<Foo> = {
b: 123,
c: true
}
const e: MyPartial<Foo> = {
a: 'aaaaa',
b: 123,
c: true
}
type MyPartial<T> = {
[P in keyof T]?: T[P]
}
Required => MyRequired
1.所有的变成必选
2.需要通过keyof将其转化为联合类型,通过-?将可选去掉
type Foo = {
a?: string
b?: number
c?: boolean
}
const a: MyRequired<Foo> = {}
// Error
const b: MyRequired<Foo> = {
a: 'asdf'
}
// Error
const c: MyRequired<Foo> = {
b: 123
}
// Error
const d: MyRequired<Foo> = {
b: 123,
c: true
}
// Error
const e: MyRequired<Foo> = {
a: 'asdf',
b: 123,
c: true
}
type MyRequired<T> = {
[P in keyof T]-?: T[P]
}
Readonly => MyReadonly
readonly此为核心思想
type Foo = {
a: string
}
const a:Foo = {
a: '123',
}
a.a = 'bigfrontend.dev'
// OK
const b:MyReadonly<Foo> = {
a: '123'
}
b.a = 'bigfrontend.dev'
// Error
type MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
Record => MyRecord
1.将联合类型转化为对象
2.判断是否在T中,然后赋值
type Key = 'a' | 'b' | 'c'
const a: Record<Key, string> = {
a: '111',
b: '222',
c: '333'
}
a.a = 'bigfrontend.dev' // OK
a.b = 123 // Error
a.d = '123123' // Error
type Foo = MyRecord<{a: string}, string> // Error
`keyof any == string | number | symbol`
type MyRecord<T extends keyof any,V> = {
[P in T]: V
}
Pick => MyPick
1.在K进行参数校验
2.循环T 进行取值
type Foo = {
a: string
b: number
c: boolean
}
type A = MyPick<Foo, 'a' | 'b'> // {a: string, b: number}
type B = MyPick<Foo, 'c'> // {c: boolean}
type C = MyPick<Foo, 'd'> // Error
type MyPick<T,K extends keyof T> = {
[P in K]: T[P]
}
Exclude => MyExclude
排除 通过extends去进行类似遍历对比 判断是否有,如果有则返回never否则返回值
type Foo = 'a' | 'b' | 'c'
type A = MyExclude<Foo,'a'> // 'b' | 'c'
type B = MyExclude<Foo,'b'> // 'a' | 'c'
type AB = MyExclude<Foo,'a' | 'b'> // 'c'
type MyExclude<T,K> = T extends K ? never : T
Omit => MyOmit
Omit获取排除的类型
1.首先先获取排除的联合类型
2.通过Pick获取排除后的对象
type Foo = {
a: string
b: number
c: boolean
}
type A = MyOmit<Foo, 'a' | 'b'> // {c: boolean}
type B = MyOmit<Foo, 'c'> // {a: string, b: number}
type C = MyOmit<Foo, 'c' | 'd'> // {a: string, b: number}
type MyExclude<T,K> = T extends K ? never : T
type MyPick<T,K extends keyof T>= {
[P in K]: T[P]
}
type MyOmit<T, K extends keyof any> = MyPick<T,MyExclude<keyof T,K>>
Extract => MyExtract
- 这个和
Exclude相反,思路看Exclude
type Foo = 'a' | 'b' | 'c'
type A = MyExtract<Foo, 'a'> // 'a'
type B = MyExtract<Foo, 'a' | 'b'> // 'a' | 'b'
type C = MyExtract<Foo, 'b' | 'c' | 'd' | 'e'> // 'b' | 'c'
type D = MyExtract<Foo, never> // never
type MyExtract<T, U> = T extends U ? T : never
# NonNullable
1.核心思路通过extends进行循环对比相等则返回never
type Foo = 'a' | 'b' | null | undefined
type A = MyNonNullable<Foo> // 'a' | 'b'
type MyNonNullable<T> = T extends null | undefined ? never : T
type MyNonNullable<T,P extends any = T> = T extends P ?
T extends null ?
never : T extends undefined ? never : T : never
# Parameters
type Foo = (a: string, b: number, c: boolean) => string
type A = MyParameters<Foo> // [a:string, b: number, c:boolean]
type B = A[0] // string
type C = MyParameters<{a: string}> // Error
type MyParameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
ConstructorParameters
[Parameters]处理的是function type。 与之类似,ConstructorParameters<T>针对的是class,返回constructor function T的其参数type组成的tuple type。
class Foo {
constructor (a: string, b: number, c: boolean) {}
}
type C = MyConstructorParameters<typeof Foo>
// [a: string, b: number, c: boolean]
type MyConstructorParameters<T extends new (...args:any) => any> = T extends new (...args: infer P) => any ? P : never
ReturnType
[Parameters]处理的是参数, ReturnType<T>,正如起名所述,处理的是function type T的返回值type
思路:
1.通过extends进行函数比对 2.其次通过infer变量暂存起来(只能在extends)中使用
2.比对成功则返回 infer变量
type Foo = () => {a: string}
type A = MyReturnType<Foo> // {a: string}
type MyReturnType<T extends () => any> = T extends () => infer P ? P : never
InstanceType
对于constructor function type T,InstanceType<T> 返回其instance type。
思路: 1.
class Foo {}
type A = MyInstanceType<typeof Foo> // Foo
type B = MyInstanceType<() => string> // Error
type MyInstanceType<T extends new () => any> = T extends new () => infer P ? P : never
ThisParameterType
对于function type T,ThisParameterType<T>返回this type。 如果没有指定,则使用unknown。
function Foo(this: {a: string}) {}
function Bar() {}
type A = MyThisParameterType<typeof Foo> // {a: string}
type B = MyThisParameterType<typeof Bar> // unknown
type MyThisParameterType<T> = T extends (this: infer P) => any ? P : unknown
OmitThisParameter
Function.prototype.bind()返回一个this已经bind过后的function。 对于这种情况,可以用OmitThisParameter<T>来增加type信息。
function foo(this: {a: string}) {}
foo() // Error
const bar = foo.bind({a: '123123123'})
bar() // OK
type Foo = (this: {a: string}) => string
type Bar = MyOmitThisParameter<Foo> // () => string
type MyOmitThisParameter<T extends (...args: any) => any> = T extends (...args: any) => infer P ? () => P : never
FirstChart
type A = FirstChar<'ABA'> // 'A'
type B = FirstChar<'dAA'> // 'd'
type C = FirstChar<''> // never
type FirstChar<T extends string> = T extends `${infer L}${infer R}` ? L : never
LastChar
type A = LastChar<'VVE'> // 'E'
type B = LastChar<'dev'> // 'v'
type C = LastChar<''> // never
type LastChar<T extends string, P = never> = T extends `${infer L}${infer R}` ? LastChar<R, L> : P
TupleToUnion
type Foo = [string, number, boolean]
type Bar = TupleToUnion<Foo> // string | number | boolean
type TupleToUnion<T extends any[], P = T[0]> = T extends [infer L, ...infer R] ? TupleToUnion<R, P | L> : P
FirstItem
type A = FirstItem<[string, number, boolean]> // string
type B = FirstItem<['B', 'C', 'D']> // 'B'
type FirstItem<T extends any[]> = T extends [infer L, ...infer R] ? L : never
LastItem
type A = LastItem<[string, number, boolean]> // boolean
type B = LastItem<['B', 'C', 'D']> // 'D'
type C = LastItem<[]> // never
type LastItem<T extends any[]> = T extends [...infer L,infer R] ? R : never
type LastItem<T extends any[],Prev extends any = never> = T extends [infer L,...infer R] ? LastItem<R,L> : Prev
IsNever
type A = IsNever<never> // true
type B = IsNever<string> // false
type C = IsNever<undefined> // false
type IsNever<T> = [T] extends [never] ? true : false
StringToTuple
type A = StringToTuple<'BCD.EFG'> // ['B', 'C', 'D', '.', 'E', 'F','G']
type B = StringToTuple<''> // []
type StringToTuple<T extends string, A extends any[] = []> = T extends `${infer L}${infer R}` ? StringToTuple<R, [...A, L]> : A
type StringToTuple<T extends string> = T extends `${infer L}${infer R}` ? [L, ...StringToTuple<R>] : []
LengthOfTuple
type A = LengthOfTuple<['B', 'C', 'D']> // 3
type B = LengthOfTuple<[]> // 0
type LengthOfTuple<T extends any[], A extends any[] = []> = T extends [infer L, ...infer R] ? LengthOfTuple<R,[...A,undefined]> : A["length"]
LengthOfString
type A = LengthOfString<'BCD.EFG'> // 7
type B = LengthOfString<''> // 0
type LengthOfString<T extends string>=StringToTuple<T>['length']
UnwrapPromise
type A = UnwrapPromise<Promise<string>> // string
type B = UnwrapPromise<Promise<null>> // null
type C = UnwrapPromise<null> // Error
type UnwrapPromise<T> = T extends Promise<infer L> ? L : never
ReverseTuple
type A = ReverseTuple<[string, number, boolean]> // [boolean, number, string]
type B = ReverseTuple<[1,2,3]> // [3,2,1]
type C = ReverseTuple<[]> // []
type ReverseTuple<T extends any[]> = T extends [infer L, ...infer R] ? [...ReverseTuple<R>, L] : []
// 参考 StringToTuple
Flat
type A = Flat<[1,2,3]> // [1,2,3]
type B = Flat<[1,[2,3], [4,[5,[6]]]]> // [1,2,3,4,5,6]
type C = Flat<[]> // []
type Flat<T extends any[], A extends any[] = []> = T extends [infer L, ...infer R] ?
// L extends any[] ? Flat<[...L, ...R], A> : Flat<R, [...A, L]>
FlatFront<L, R, A>
: A
type FlatFront<T, R extends any[], A extends any[] = []> = T extends any[] ? Flat<[...T, ...R], A> : Flat<R, [...A, T]>