为什么TypeScript中的'instanceof'给我错误"'Foo'只引用一个类型,但在这里被用作值."?

Dan*_*ser 60 javascript instanceof typescript

我写了这段代码

interface Foo {
    abcdef: number;
}

let x: Foo | string;

if (x instanceof Foo) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但是TypeScript给了我这个错误:

'Foo' only refers to a type, but is being used as a value here.
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*ser 68

这是怎么回事

问题是,instanceof是从JavaScript构建,并在JavaScript中,instanceof需要一个的右侧操作数.具体来说,在x instanceof FooJavaScript中将执行运行时检查以查看是否Foo.prototype存在于原型链中的任何位置x.

但是,在TypeScript中,interfaces没有发射.这意味着在运行时既不存在Foo也不Foo.prototype存在,所以这段代码肯定会失败.

TypeScript试图告诉你这可能永远不会奏效.Foo只是一种类型,它根本不是一个价值!

"我能做什么而不是instanceof?"

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

"但是,如果我只是从一个切换interface 到一个class?"

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

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;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,你有xy那个类型相同,但是如果你尝试使用instanceof任何一个,你将得到相反的结果.因此,如果您正在利用TypeScript中的结构类型,那么对于类型instanceof将不会真正告诉您.

  • 这里的要点是`instanceof` 与类一起工作,而不是接口。认为需要强调这一点。 (15认同)

Lee*_*iam 11

如果您希望检查的接口具有不同的属性/功能,则在运行时使用接口进行类型检查是使用类型保护

例子

let pet = getSmallPet();

if ((pet as Fish).swim) {
    (pet as Fish).swim();
} else if ((pet as Bird).fly) {
    (pet as Bird).fly();
}
Run Code Online (Sandbox Code Playgroud)