Typescript手写工具类型
起因工具类型手写工具类型Pick<Type, Keys>Omit<Type, Keys>Recod<K, T>Exclude<T, U>Extract<T, U>NonNullable<Type>Required<T>Partial<T>Readonly<T>Parameters<Type>ReturnType<Type>ConstructorParameters<Type>InstanceType<T>ThisParameterType<Type>OmitThisParameter<Type>参考
起因
之前有次面试的时候和面试官说了句熟悉Typescript,
面试官:那你手写一下Pick类型
我:………
面试官:……..
还是要保持一颗谦虚学习的心🤣🤣🤣🤣🤣
工具类型
Typescript提供一些官方工具类型,这些工具类型全局可用, 无需手动导入,通过使用这些工具类型可以减少很多重复工作,提高效率和代码整洁度。
Typescript工具类型详细介绍可以见TypeScript实用工具
手写工具类型
Pick<Type, Keys>
type MyPick<Type, Keys extends keyof Type> = { [P in Keys]: Type[P] }
Omit<Type, Keys>
type MyOmit<Type, Keys extends keyof Type> = { [P in Exclude<keyof Type, Keys>]: Type[P] }
Omit的作用与Pick相反,也可以借助Pick来实现Omit。
type MyOmit<Type, Keys extends keyof Type> = Pick<Type, Exclude<keyof Type, Keys>>
Recod<K, T>
type MyRecord<K extends string | number | symbol, T> = { [R in K]: T }
Exclude<T, U>
type MyExclude<T, U> = T extends U ? never : T;
Extract<T, U>
type MyExtract<T, U> = T extends U ? T : never;
NonNullable<Type>
type MyNonNullable<T> = Exclude<T, undefined | null> // 即 type MyNonNullable<T> = T extends null | undefined ? never : T; // 或者 type MyNonNullable<T> = T & {}
Required<T>
type MyRequired<T> = { [K in keyof T]-?: T[K] }
这里的
-?
符号看起来很容易让人懵逼,事实上这的-
号是控制映射类型修饰符的,除此之外还有+
号,可以通过-
和+
号来修改属性readonly或者属性可选。 也就是说上面的-?
意思是remove ?
,同理,+?
、+readonly
分别是添加属性可选、添加属性可读的意思,但是通常情况下我们可以省略+
,因为不写和写+
的效果是一样的。Partial<T>
根据上面的介绍,我们可以很容易想到利用
+?
来实现Partial,也可以省略+
。type MyPartial<T> = { [K in keyof T]?: T[K] }
Readonly<T>
type MyReadonly<T> = { +readonly [K in keyof T]: T[K] }
我们也可以写出移除readonly属性的工具类型:
type RemoveReadonly<T> = { -readonly [K in keyof T]: T[K] }
甚至可以实现一个让数组里每个元素都readonly的工具类型。
type MyReadonlyArray<T> = { +readonly [P in number]: T }
Parameters<Type>
type MyParameters<T extends (...args: any[])=>any> = T extends (...args: infer P)=>any ? P : never
ReturnType<Type>
type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any) => infer P ? P : any
ConstructorParameters<Type>
type MyConstructorParameters<T extends abstract new (...args: any[]) => any> = T extends abstract new (...args: infer P) => any ? P : never
InstanceType<T>
type MyInstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
ThisParameterType<Type>
type MyThisParameterType<T> = T extends (this: infer P, ...args:never)=>any ? P : unknown;
OmitThisParameter<Type>
type MyOmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T