Typescript学习笔记——类型体操记录

73 阅读1分钟

联合类型循环

想要做到循环联合类型的话需要3个知识点:

  1. 重载函数在使用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'
  1. 将相同的函数类型进行交叉,等价于函数重载
type Fn = {
    (): 'b';
    (): 'a';
};
type Fn2 = (() => 'b') & (() => 'a');
type Res = Fn2 extends Fn ? true : false;  // true
  1. 类型体操是可以递归的

实现:

/**
 * 联合类型 => 交叉函数类型(函数重载)
 * @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,有兴趣的可以看一下~。