我正在尝试为API提供一个函数,该函数接受可以是A或B类型的参数。我使用interfaces
来键入参数。这些类型不共享一个成员。我的尝试导致编译器抱怨x类型上没有属性x。
export interface MyTypeA {
prop1: string;
prop2: boolean;
}
export interface MyTypeB {
prop3: number;
prop4: string;
}
doSomething(param1: string, param2: MyTypeA | MyTypeB){
switch(param1){
case 'a':
case 'b': {
const cf = this.resolver.resolveComponentFactory(MyClassAComponent);
const component = this.wrap.createComponent(cf);
component.instance.prop1 = param2.prop1;
component.instance.prop2 = param2.prop2;
break;
}
case 'c': {
const cf = this.resolver.resolveComponentFactory(MyClassBComponent);
const component = this.wrap.createComponent(cf);
component.instance.prop3 = param2.prop3;
break;
}
}
}
我不确定interface
可以做到这一点,我想我可能不得不使用type
,但不知道如何做。
答案 0 :(得分:4)
我看到了3种可能的解决方案:
param2
的每一次使用。如果您将param1
和param2
结合起来,我会选择Tagged Unions。否则使用用户定义的类型保护。
如果你不得不多次使用它,我觉得太冗长,但是最直接的解决方案:
...
component.instance.prop1 = (param2 as MyTypeA).prop1;
component.instance.prop2 = (param2 as MyTypeA).prop2;
...
此解决方案不会生成其他代码(演员表将从生成的代码中完全删除)。
您可以合并param1
和param2
并将自定义类型转换为tagged unions:
export interface MyTypeA {
param1: 'a' | 'b';
prop1: string;
prop2: boolean;
}
export interface MyTypeB {
param1: 'c';
prop3: number;
prop4: string;
}
doSomething(param2: MyTypeA | MyTypeB) {
switch(param2.param1) {
case 'a':
case 'b': {
// The compiler knows param2 is of type MyTypeA, because its param1
// property is either 'a' or 'b'.
const cf = this.resolver.resolveComponentFactory(MyClassAComponent);
const component = this.wrap.createComponent(cf);
component.instance.prop1 = param2.prop1;
component.instance.prop2 = param2.prop2;
break;
}
case 'c': {
// The compiler knows param2 is of type MyTypeB, because its param1
// property is 'c'.
const cf = this.resolver.resolveComponentFactory(MyClassBComponent);
const component = this.wrap.createComponent(cf);
component.instance.prop3 = param2.prop3;
break;
}
}
}
此解决方案不会生成其他代码(接口,包括标记的参数,将不会出现在生成的代码中)。
您可以使用User Defined Type Guards缩小param2
的类型:
export interface MyTypeA {
prop1: string;
prop2: boolean;
}
export interface MyTypeB {
prop3: number;
prop4: string;
}
function isA(arg: any): arg is MyTypeA {
return arg.hasOwnProperty('prop1');
}
function isB(arg: any): arg is MyTypeB {
return arg.hasOwnProperty('prop3');
}
doSomething(param1: string, param2: MyTypeA | MyTypeB) {
switch(param1) {
case 'a':
case 'b': {
if (!isA(param2)) return;
// The compiler knows param2 is of type MyTypeA:
const cf = this.resolver.resolveComponentFactory(MyClassAComponent);
const component = this.wrap.createComponent(cf);
component.instance.prop1 = param2.prop1;
component.instance.prop2 = param2.prop2;
break;
}
case 'c': {
if (!isB(param2)) return;
// The compiler knows param2 is of type MyTypeB:
const cf = this.resolver.resolveComponentFactory(MyClassBComponent);
const component = this.wrap.createComponent(cf);
component.instance.prop3 = param2.prop3;
break;
}
}
}
请注意,此解决方案将生成其他代码,因为这些isA
和isB
函数以及对它们的调用都将包含在生成的代码中。