为什么TypeScript中的'instanceof'给我一个错误“'Foo'仅指一种类型,但在这里被用作值。

2022-08-30 02:07:48

我写了这个代码

interface Foo {
    abcdef: number;
}

let x: Foo | string;

if (x instanceof Foo) {
    // ...
}

但是TypeScript给了我这个错误:

'Foo' only refers to a type, but is being used as a value here.

为什么会发生这种情况?我认为这可以检查我的值是否具有给定的类型,但TypeScript似乎不喜欢这样。instanceof


答案 1

TL;DR

instanceof适用于类,而不是接口或类型别名。


TypeScript 想告诉我什么?

问题是,instanceof 是来自 JavaScript 的构造,在 JavaScript 中,它期望右侧操作数的值。具体来说,在 JavaScript 中将执行运行时检查,以查看 是否存在于 原型链中的任何位置。instanceofx instanceof FooFoo.prototypex

但是,在 TypeScript 中,s 没有 emit。别名也是如此。这意味着在运行时既不存在,也不存在,因此此代码肯定会失败。interfacetypeFooFoo.prototype

TypeScript试图告诉你这永远行不通。 只是一种类型,它根本不是一个值!Foo

如果你来自另一种语言,你可能打算在这里使用一个类。类确实在运行时创建值,但您可能希望在下面阅读一些有关此内容的注释。

“如果我仍然想要一个或,我该怎么办?”instanceoftypeinterface

您可以查看类型保护和用户定义的类型保护

“但是,如果我只是从 a 切换到 a 呢?”interfaceclass

您可能想从 a 切换到 a,但您应该意识到,在 TypeScript 的结构类型系统(其中事物主要基于形状)中,您可以生成与给定类具有相同形状的任何对象:interfaceclass

class C {
    a: number = 10;
    b: boolean = true;
    c: string = "hello";
}

let x = new C()
let y = {
    a: 10, b: true, c: "hello",
}

// Works!
x = y;
y = x;

在这种情况下,您有和具有相同的类型,但是如果您尝试在任何一个上使用,您将在另一个上得到相反的结果。因此,如果您利用TypeScript中的结构类型,则不会真正告诉您有关该类型的太多信息。xyinstanceofinstanceof


答案 2

在运行时使用接口进行类型检查是使用类型保护,如果要检查的接口具有不同的属性/函数。

let pet = getSmallPet();

if ((pet as Fish).swim) {
    (pet as Fish).swim();
} else if ((pet as Bird).fly) {
    (pet as Bird).fly();
}