实例和类型断言



如果我有以下类,则在打字稿中:

class Hello{
  public world: string;
}

为什么当我键入断言解析的 json 作为 Helloinstanceof返回 false?

var json: string = `{"world": "world"}`;
var assertedJson: Hello = JSON.parse(json) as Hello;
var hello: Hello = new Hello();
console.log(assertedJson instanceof Hello); <!-- returns false
console.log(hello instanceof Hello); <!-- returns true (as expected)
原因是

instanceof被"按原样"转换为JavaScript。如果您转译代码,您会得到:

var Hello = /** @class */ (function () {
    function Hello() {
    }
    return Hello;
}());
var json = "{"world": "world"}";
var assertedJson = JSON.parse(json);
var hello = new Hello();
console.log(assertedJson instanceof Hello);
console.log(hello instanceof Hello);

a instanceof b检查 b 的原型是否在 a 的原型链中。您的assertedJson不符合此要求。

as运算符在转译时没有任何意义,只是一个注释

正如其他人所说,您使用 as 进行的类型转换对运行时没有影响。但是,作为一种解决方法,您可以手动设置解析对象的原型,以便它将成为Hello的实例,如果您愿意的话:

class Hello {
    public world: string;
    public sayHello() {
        console.log("Hello", this.world);
    }    
}
var json: string = `{"world": "world"}`;
var assertedJson: Hello = JSON.parse(json) as Hello;
var hello: Hello = new Hello();
console.log(assertedJson instanceof Hello); // <!-- returns false
console.log(hello instanceof Hello); // <!-- returns true (as expected)
// Manual fix:
Object.setPrototypeOf(assertedJson, Hello.prototype);
console.log(assertedJson instanceof Hello); // <!-- returns true
// And doing so will then allow you to access the Hello methods too:
assertedJson.sayHello() // Prints "Hello world"

类型断言仅适用于编译时的编译器,在运行时没有任何影响。开发人员有责任确保编译时类型断言与运行时行为匹配。

instanceof是运行时检查,基本上检查对象是否是使用特定的类构造函数创建的。它对 JSON 对象没有多大用处,因为它们是作为内置 Object 类型的实例创建的。

TypeScript 开发人员关于支持与类型系统一致的运行时类型检查的答案是:

https://github.com/Microsoft/TypeScript/issues/2444#issuecomment-85097544

这已经被提出和讨论过很多次了。我们一直在努力 以避免将类型系统推入运行时和 这实际上适用于的类型(几乎只是类和 原语(不够大,不足以证明复杂性与 它支持的用例。

最新更新