【问题标题】:Typescript Constructor Parameter Factory TypingTypescript 构造函数参数工厂类型
【发布时间】:2021-02-07 03:19:38
【问题描述】:

我的类的构造函数需要形成标记联合的对象:

interface Info {
  x: string;
}

interface AInfo extends Info {
  x: 'a';
}

class A {
  constructor(info: AInfo) {}
}

interface BInfo extends Info {
  x: 'b';
}

class B {
  constructor(info: BInfo) {}
}

type AllInfos = AInfo|BInfo;

我省略了类内部和构造函数初始化。如何键入此工厂函数以关联根据传入的信息创建的对象类型?

const factory = (info: AllInfos) => {
  switch (info.x) {
    case 'a': return new A(info);
    case 'b': return new B(info);
    // ...
  }
};

const obj = factory(myInfo); // type of obj is A|B, I'd like it to vary by myInfo

【问题讨论】:

    标签: typescript generics typescript-typings


    【解决方案1】:

    最简单的方法是使用重载:

    function factory(info: AInfo): A
    function factory(info: BInfo): B
    function factory(info: AllInfos) {
      switch (info.x) {
        case 'a': return new A(info);
        case 'b': return new B(info);
        // ...
      }
    };
    
    const objA = factory({ x: 'a' }); // A
    const objB = factory({ x: 'b' }); // B
    

    Playground Link

    如果union中有很多选项,你可以创造性地创建一个分布式条件类型,为union中的每个成员创建一个签名,然后使用UnionToIntersection使其成为重载签名(见@ 987654322@):

    type UnionToIntersection<U> = 
      (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
    
    type Factory<T> = T extends new (p: infer P) => infer R ? (a: P) => R : never
    type FactoryParameters<T> = T extends new (p: infer P) => infer R  ? P : never
    type AllClasses = typeof A | typeof B
    
    const factory = ((info: FactoryParameters<AllClasses>) => {
      switch (info.x) {
        case 'a': return new A(info);
        case 'b': return new B(info);
      }
    }) as UnionToIntersection<Factory<AllClasses>>;
    
    const objA = factory({ x: 'a' }); // A
    const objB = factory({ x: 'b' }); // B
    

    Playground Link

    【讨论】:

      猜你喜欢
      • 2019-03-23
      • 2015-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多