将对象类型转换为Angulars Type <t>

时间:2018-06-21 11:47:23

标签: angularjs typescript types

我有一个组件列表,一个AnyComponent类型和一个用于查找组件的函数:

const components = [Comp1, Comp2, Comp3 ...];

type AnyComponent = typeof components[number];

findComponent(id: string): AnyComponent|undefined {
  return components.find(comp => comp.id === id);
}

问题是findComponent返回此类型:

typeof Comp1 | typeof Comp2 | typeof Comp3

但是我需要使用的下一个函数(角度resolveComponentFactory)要求它是Type<AnyComponent>Type<typeof Comp1 | typeof Comp2 | typeof Comp3>

如果我将findComponent的返回值设置为Type<AnyComponent>,则会收到一条错误消息,指出它不可分配。

但是,如果我将AnyComponent更改为此:

type AnyComponent = Comp1 | Comp2 | Comp3;

然后我只能将findComponent返回值设置为Type<AnyComponent>,并且一切正常。

使用联合工作的全部问题在于,我必须对每个组件声明两次,而我实际上正在寻找一种只定义一次的方法。

那么有没有办法让findComponent返回Type<AnyComponent>

1 个答案:

答案 0 :(得分:1)

AnyComponent包含类类型的并集(即typeof Comp1)。 T中的Type<T>期望T是实例类型(即Comp1)。幸运的是,Typescript具有InstanceType<T>可以从类类型中提取实例类型。

我们可能希望可以做Type<InstanceType<AnyComponent>>,但是由于类型new (...args: any[]) => T的定义会导致

Type<InstanceType<AnyComponent>> == new (...args: any[]) => Comp1 | Comp2 | Comp3

这是无法从Comp1分配的,我们想要的是将实例联合以Type<T>的联合分配,为此,我们需要一个条件类型:

// Dummy 
class Comp1 { static id:string; private s: string}
class Comp2 { static id:string; private s: string}
class Comp3 { static id:string; private s: string}
type Type<T> = new (...args: any[]) => T;

const components = [Comp1, Comp2, Comp3];

type AnyComponent = typeof components[number];
// Conditional type to transform the union of instance type into a union of Type<T>
type TypeUnion<T> = T extends any ? Type<T> : never; 

function findComponent(id: string): TypeUnion<InstanceType<AnyComponent>>|undefined {
    return components.find(comp => comp.id === id);
}