我写了这段代码
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.
为什么会发生这种情况?我以为instanceof
可以检查我的值是否具有给定的类型,但TypeScript似乎不喜欢这样。
6条答案
按热度按时间vaqhlq811#
靶区; DR
instanceof
使用类,而不是接口或类型别名。TypeScript想告诉我什么?
问题在于
instanceof
是JavaScript的一个构造,在JavaScript中,instanceof
的右边操作数需要一个 * value *,具体来说,在x instanceof Foo
中,JavaScript将执行运行时检查,以查看Foo.prototype
是否存在于x
的原型链中的任何位置。但是,在TypeScript中,
interface
没有emit,type
别名也是如此,这意味着Foo
和Foo.prototype
在运行时都不存在,所以这段代码肯定会失败。TypeScript试图告诉你这永远不可能成功。
Foo
只是一个类型,它根本不是一个值!如果你来自另一种语言,你可能想在这里使用一个类。类在运行时创建值,但是你可能想阅读下面的一些注解。
"如果我仍然需要
type
或interface
,除了instanceof
,我可以做什么?"您可以查看类型保护和用户定义的类型保护。
"但如果我只是从
interface
切换到class
呢?"您可能会尝试从
interface
切换到class
,但您应该意识到,在TypeScript的结构类型系统中(其中的内容主要是 * 基于形状的 *),您可以生成与给定类具有相同形状的任何对象:在本例中,
x
和y
具有相同的类型,但如果您尝试在其中一个上使用instanceof
,则在另一个上会得到相反的结果。因此,如果您正在利用TypeScript中的结构类型,instanceof
不会"真正"告诉您关于类型的很多信息。oyxsuwqo2#
如果您希望检查的接口具有不同的属性/函数,则在运行时对接口执行类型检查是使用类型保护。
示例
v6ylcynt3#
丹尼尔Rosenwasser可能是对的,但我想对他的答案做一个修正。检查x的示例是完全可能的,请参阅代码片段。
但是赋值x = y也同样容易,现在x不是C的一个示例,因为y只有C的形状。
s4n0splo4#
当检查对象是否符合接口签名时,我认为适当的方法是考虑使用“类型 predicate ”:https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
5f0d552i5#
您可以使用in运算符缩小范围来检查所需的元素是否在对象中。
使用此方法,可以验证x是字符串还是Foo
xriantvc6#
instanceof
通常是正确答案。然而,在我的例子中,我使用的是一个基元类型,
instanceof Number
和instanceof number
在ts编译器中都出错了:使用基元类型时,
typeof
是正确答案: