如何在Typescript中检查对象的类型

28 浏览
0 Comments

如何在Typescript中检查对象的类型

我写了这段代码:

interface Foo {
    abcdef: number;
}
let x: Foo | string;
if (x instanceof Foo) {
    // ...
}

但是TypeScript给了我这个错误:

'Foo'只能引用类型,但在此处被用作值。

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

0
0 Comments

如何在Typescript中检查对象的类型

在Typescript中,我们经常需要检查一个对象的类型。通常,我们可能会使用instanceof操作符来进行类型检查。然而,当我们尝试在Typescript中使用instanceof操作符时,会遇到一些问题。

问题的原因是,instanceof是JavaScript中的一个构造函数,它期望右侧操作数是一个值。在JavaScript中,instanceof会在运行时检查对象的原型链,以确定对象是否是某个类的实例。然而,在Typescript中,接口和类型别名都没有运行时表示,因此instanceof操作符无法正常工作。

Typescript会告诉你,这样的代码是无法工作的。接口和类型别名只是类型,根本没有对应的值。

那么,在Typescript中,我们该如何检查对象的类型呢?

一个解决方法是使用类型保护和用户自定义类型保护。通过定义一些条件判断,我们可以在代码中使用这些类型保护来进行类型检查。

另一个解决方法是将接口转换为类。然而,在Typescript的结构类型系统中,类的实例只是具有与给定类相同形状的对象。因此,如果我们使用instanceof操作符来检查这些实例的类型,可能会得到错误的结果。

如果我们需要在Typescript中检查对象的类型,我们应该避免使用instanceof操作符,而是使用类型保护和用户自定义类型保护来进行类型检查。

参考链接

- [TypeScript Handbook: Type Guards and Differentiating Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types)

0
0 Comments

在TypeScript中,有时候我们需要检查一个对象的类型。例如,在上述代码中,我们创建了一个类C,然后创建了一个实例x和一个对象y。我们想要检查x和y的类型是不是C类的实例。

然而,使用instanceof操作符来检查对象的类型并不总是有效。在上述代码中,尽管y的结构与C类相同,但它并不是C类的实例。因此,使用instanceof操作符检查y的类型会返回false。

那么,为什么会出现这个问题呢?这是因为TypeScript中的类型检查是基于结构而不是基于类的。换句话说,TypeScript并不关心对象的具体类,而是关注对象的结构。因此,即使对象的结构与某个类相同,也不能保证它是该类的实例。

那么,有没有其他方法来检查对象的类型呢?当然有!一种常用的方法是使用typeof操作符。typeof操作符可以用来检查一个对象的类型是否为特定的基本类型,如字符串、数字、布尔值等。但是,它无法检查一个对象是否是某个类的实例。

另一种方法是使用类型断言。类型断言可以告诉编译器,在某个特定的上下文中,我们知道对象的类型是什么。在上述代码中,我们可以使用类型断言来告诉编译器,y是C类的实例。具体做法是将y的类型断言为C类,如下所示:

let y = {
    a: 10, b: true, c: "hello",
} as C;

通过使用类型断言,我们告诉编译器将y视为C类的实例。这样,我们就可以使用instanceof操作符来检查y的类型了。

总结起来,要想检查一个对象的类型,我们可以使用instanceof操作符、typeof操作符或者类型断言。然而,在使用这些方法时,我们需要注意它们的局限性,以及对象的结构和类之间的关系。

0
0 Comments

在TypeScript中,我们可以使用类型守卫(type guards)在运行时进行类型检查,特别是当我们希望检查的接口具有不同的属性/函数时。例如:

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

但是,如果我们了解到鸭子(Duck)并将swim()函数添加到Bird接口中,那么每个宠物都会在类型守卫中被分类为鱼(Fish)吗?如果有三个接口,每个接口有三个函数,并且有两个接口与另一个接口重叠了,会怎么样呢?

如果没有能够唯一标识接口的属性/函数,我们无法真正区分它们。你的宠物可能实际上是一只鸭子(Duck),但在类型守卫中被标记为鱼(Fish),但在调用swim()时仍然不会出现运行时异常。建议您创建一个共同的一级接口(例如Swimmable),将swim()函数移动到其中,然后类型守卫仍然可以使用((pet as Swimmable).swim)。

为了避免类型转换,您可以使用'swim' in pet条件来进行判断。它将将宠物的类型缩小为必须定义swim的子集(例如Fish | Mammal)。

通过使用类型守卫和适当的类型判断,我们可以在TypeScript中在运行时检查对象的类型。

0