class A {
type: string
}
interface AClass<T extends A> {
prototype: T
}
function isType<T extends A>(a: A, aClass: AClass<T>): a is T {
return a.type === aClass.prototype.type
}
class B extends A {
foo: string
}
class C extends A {}
function check(a: A) {
if (isType(a, B)) {
return
}
a.type // ok
if (isType(a, C)) {
return
}
a.type // Property 'type' does not exist on type 'never'.
}
当派生类没有任何独特属性时,会出现错误。这是在我将TS更新到2.1.4之后发生的。我的问题是:
为什么这里有错误?我的猜测是TS会绕过自定义类型检查并对A
和C
进行处理,因为它们具有相同的类型,因此无法访问下一个语句,a
将具有类型{{1 }}
有没有比向派生类添加虚拟属性更好的解决方案?
答案 0 :(得分:1)
你是对的,因为A
和C
被编译器认为是相同的类型,因为它们具有相同的确切结构(Type Compatibility)。
你不应该添加虚拟属性,如果C
没有其他成员/方法,那么无论如何它都没有意义,你可以使用A
和B
。
你可以这样做:
class A {
type: "B" | "C";
}
class B extends A {
type: "B";
foo: string
}
class C extends A {
type: "C";
}
编译器现在不会抱怨,但是你可以获得完全相同的东西:
class A {
type: string;
constructor(type: string = "A") {
this.type = type;
}
}
class B extends A {
foo: string;
constructor(foo: string) {
super("B");
this.foo = foo;
}
}
let a = new A();
let b = new B("foo");
let c = new A("C");
type
和a
之间的c
属性不同,即使它们是同一类的实例。