将打字稿从2.0.3更新到2.1.4后输入防范错误

时间:2016-12-12 09:24:45

标签: typescript typescript2.0 typescript2.1

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会绕过自定义类型检查并对AC进行处理,因为它们具有相同的类型,因此无法访问下一个语句,a将具有类型{{1 }}

  • 有没有比向派生类添加虚拟属性更好的解决方案?

1 个答案:

答案 0 :(得分:1)

你是对的,因为AC被编译器认为是相同的类型,因为它们具有相同的确切结构(Type Compatibility)。

你不应该添加虚拟属性,如果C没有其他成员/方法,那么无论如何它都没有意义,你可以使用AB

修改

你可以这样做:

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");

typea之间的c属性不同,即使它们是同一类的实例。