联合类型循环
想要做到循环联合类型的话需要3个知识点:
- 重载函数在使用infer进行推断时,会取重载部分的最后一个声明
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type Fn = {
(): 'b';
(): 'a';
};
type Res = ReturnType<Fn>; // 'a'
- 将相同的函数类型进行交叉,等价于函数重载
type Fn = {
(): 'b';
(): 'a';
};
type Fn2 = (() => 'b') & (() => 'a');
type Res = Fn2 extends Fn ? true : false; // true
- 类型体操是可以递归的
实现:
/**
* 联合类型 => 交叉函数类型(函数重载)
* @example 1 | 2 | 3 => (() => 1) & (() => 2) & (() => 3)
*/
export type UnionToFnIntersection<T> = (
T extends any ? (arg: () => T) => void : never
) extends (arg: infer P) => void
? P
: never;
/**
* 推断出来的 R 就是联合类型的最后一个声明,可以在此基础上给 R 做其他操作
*/
export For<T> = UnionToFnIntersection<T> extends () => infer R
? R | For<Exclude<T, R>>
: never;
联合对象类型相同的对象属性变联合,不相同的属性变交叉
解释:把{ a: number } | { a: string; b: string } => { a: number | string; b: string };
/**
* 联合类型 => 交叉类型
*/
type UnionToIntersection<T> = (T extends any ? (arg: T) => void : never) extends (T: infer P) => void
? P
: never;
type ObjectUnion<T> = T & Omit<UnionToIntersection<T>, keyof T>;
扩展
以上两种类型体操也是ab-hoc把多个组件的Props类型结合的原理
ab-hoc是一个基于策略模式处理A/B实验组件的库,支持vue3&react,有兴趣的可以看一下~。