得到错误的确切原因是什么
类型'never'不存在属性'descriminator'。
第67和70行。
type DescriminatorType = 'SubClassA' | 'SubClassB' | 'SubClassC'
使用静态类型保护函数定义一些抽象基类
export abstract class BaseClass {
constructor(
public descriminator: string,
) {
}
// tpye-guard function for SubClassA
public static isSubClassA(o: BaseClass): o is SubClassA {
return o instanceof SubClassA;
// Or
// return o.descriminator === 'SubClassA';
}
// tpye-guard function for SubClassB
public static isSubClassB(o: BaseClass): o is SubClassB {
return o instanceof SubClassB;
// Or
// return o.descriminator === 'SubClassA';
}
// tpye-guard function for SubClassC
public static isSubClassC(o: BaseClass): o is SubClassC {
return o instanceof SubClassC;
// Or
// return o.descriminator === 'SubClassA';
}
}
定义一些子类。当前,其中两个具有相同的界面。
export class SubClassA extends BaseClass {
constructor(
) {
super('SubClassA');
}
}
export class SubClassB extends BaseClass {
constructor(
) {
super('SubClassB');
}
}
export class SubClassC extends BaseClass {
constructor(
public subClassProp1: number,
) {
super('SubClassC');
}
}
定义一些利用类型保护功能的程序逻辑:
export class OtherClass {
data = [new SubClassA(), new SubClassA(), new SubClassB(), new SubClassC(123)]
public doSomething(): string[] {
return this.data.map(d => {
if (BaseClass.isSubClassA(d)) {
return d.descriminator;
}
else if (BaseClass.isSubClassB(d)) {
return d.descriminator; // Error: Property 'descriminator' does not exist on type 'never'.
}
else if (BaseClass.isSubClassC(d)) {
return d.descriminator; // Error: Property 'descriminator' does not exist on type 'never'.
}
else {
return 'UNKNOWN TYPE';
}
})
}
}
正如您在运行时在StackBlitz中看到的那样,一切正常。我正在获得预期的输出!
答案 0 :(得分:3)
打字稿类型系统本质上是结构性的。如果两个类型分别声明为BaseClass
和SubClassA
,但结构相同,则就类型系统而言,它们是完全相同的类型(至少在大多数实际情况下)
类型防护在else分支上工作,方法是从联合中取出与类型防护匹配的类型。由于SubClassB
与SubClassA
具有相同的结构,因此也将其从联合中删除(本质上,它们是同一类型,但名称不同)
SubClassC
之所以被删除,是因为类型保护也会取出匹配类型的子类型,并且由于SubClasssA
与BaseClass
是同一类型,因此SubClassC
从技术上来说是说来,SubClassA
如果没有其他类型需要处理,所有这些将导致else分支,而d
将是never
类型
在这种情况下,最简单的解决方案是将discriminator
保留为BaseClass
上的类型参数,这样,类在结构上会有所不同(使用此类型参数作为{{1 }},未使用的类型参数不计入结构):
discriminator