基础
掌握简单的泛型函数的书写了吗?
是的
进阶
ReturnType 泛型函数的实现?
关键点1 利用条件判断类型, extends 在这里是用来判断是否相等或是其subtype
type NumOrStr<T> = T extends number ? number : string // 条件判断
关键点2 限制传入的参数是函数类型
type IsFnType<T> = T extends (...args: any) => any ? true : false // 条件判断
关键点3 利用条件判断类型中的 infer 来提取出函数类型中的可变返回参数类型
type ReturnGeneric<T> = T extends (...args: any) => infer R ? R : any // 条件判断
Parameters 泛型函数?
利用条件判断类型中的 infer 来提取出函数类型中的可变传入参数类型
// Parameters<Type> => Tuple Type
type ParamsGeneric<T extends (...args: any) => any> = T extends (
...args: infer ArgsType
) => any
? ArgsType
: any; // 条件判断
type P0 = ParamsGeneric<() => string>;
type P1 = ParamsGeneric<(a: string | number) => string>;
ConstructorParameters怎么实现?
通过类型系统中泛型函数特殊的循环排除语法去做到
// ConstructorParameters<Type>
type T0 = ConstructorParameters<ErrorConstructor>;
// 限制传入参数符合 abstract new (...args: any) => any 即能通过 new Fn() 调用
// 通过条件判断类型关键字 infer 提取 args
type ConstructorGeneric<T extends abstract new (...args: any) => any> =
T extends abstract new (...args: infer P) => any ? P : never;
interface Book {
new(author: string, title: string): void;
}
type T1 = ConstructorGeneric<Book>
type T2 = ConstructorGeneric<DateConstructor>
InstanceType 泛型函数实现?
提取返回的实例
关键点还是 限制参数,通过条件判断类型中的 infer 提取返回参数
type InstanceGeneric<T extends abstract new (...args: any) => any> =
T extends abstract new (...args: any) => infer InstanceType ? InstanceType : never;
ThisParameterType => ThisType | unknown?
type toHex = (this: number) => string;
type T0 = ThisParameterType<toHex>;
type ThisGeneric<T> = T extends (this: infer ThisType, ...args: never) => any
? ThisType
: unknown;
type T1 = ThisParameterType<toHex>;
OmitThisParameter 去除this: Type?
第一个判断 unknown extends ThisParameterType 没有 this parameters 直接返回 T
第二个判断 T 有 this parameters 即符合 (this: any,...args: any) => any,直接 infer 提取 args , 返回参数类型组成去除this parameters的类型 (...args: A) => R
type toHex = (this: number) => string;
type T0 = OmitThisParameter<toHex>;
type OmitThisGeneric<T> = unknown extends ThisParameterType<T>
? T
: T extends (...args: infer A) => infer R
? (...args: A) => R
: T;
type T1 = OmitThisGeneric<toHex>;
type T2 = OmitThisGeneric<string>;