我有一个组件列表,一个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>
?
答案 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);
}