Javascript 为什么 TypeScript 中的 'instanceof' 给我错误“'Foo' 仅指一种类型,但在此处用作值。”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46703364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:33:31  来源:igfitidea点击:

Why does 'instanceof' in TypeScript give me the error "'Foo' only refers to a type, but is being used as a value here."?

javascripttypescriptinstanceof

提问by Daniel Rosenwasser

I wrote this code

我写了这段代码

interface Foo {
    abcdef: number;
}

let x: Foo | string;

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

But TypeScript gave me this error:

但是 TypeScript 给了我这个错误:

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

Why is this happening? I thought that instanceofcould check whether my value has a given type, but TypeScript seems not to like this.

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

回答by Daniel Rosenwasser

What's going on

这是怎么回事

The issue is that instanceofis a construct from JavaScript, and in JavaScript, instanceofexpects a valuefor the right-side operand. Specifically, in x instanceof FooJavaScript will perform a runtime check to see whether Foo.prototypeexists anywhere in the prototype chain of x.

问题是,instanceof是从JavaScript构建,并在JavaScript中,instanceof需要一个的右侧操作数。具体而言,在x instanceof FooJavaScript的执行运行时检查,看是否Foo.prototype在原型链中任何地方存在x

However, in TypeScript, interfaces have no emit. That means that neither Foonor Foo.prototypeexist at runtime, so this code will definitely fail.

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

TypeScript is trying to tell you this could neverwork. Foois just a type, it's not a value at all!

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

"What can I do instead of instanceof?"

“我能做什么来代替instanceof?”

You can look into type guards and user-defined type guards.

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

"But what if I just switched from an interfaceto a class?"

“但如果我只是从 an 切换interface到 aclass呢?”

You might be tempted to switch from an interfaceto a class, but you should realize that in TypeScript's structural type system (where things are primarily shape based), you can produce any an object that has the same shape as a given class:

您可能很想从 an 切换interface到 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;

In this case, you have xand ythat have the same type, but if you try using instanceofon either one, you'll get the opposite result on the other. So instanceofwon't reallytell you much about the type if you're taking advantage of structural types in TypeScript.

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

回答by Lee Chee Kiam

To do type checking at runtime with an interface is using type guards, if interfaces you wish to check have differentproperties/functions.

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

Example

例子

let pet = getSmallPet();

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

回答by Elias Vesterlund

Daniel Rosenwasser might be right and dandy but i feel like doing an amendment to his answer. It is fully possible to check instance of x, see the code snippet.

Daniel Rosenwasser 可能是对的和花哨的,但我想对他的回答进行修正。完全可以检查 x 的实例,请参阅代码片段。

But it's equally easy to assign x = y. Now x would not be an instance of C as y only had the shape of C.

但是分配 x = y 同样容易。现在 x 不会是 C 的实例,因为 y 只有 C 的形状。

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

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

console.log('x is C? ' + (x instanceof C)) // return true
console.log('y is C? ' + (y instanceof C)) // return false