TypeScript 中 检查 Object 是否是 Class 的实例

使用 instanceof 运算符检查对象是否是类的实例,例如 if (myObj instanceof MyClass) {}。 instanceof 运算符检查构造函数的原型属性是否出现在对象的原型链中,如果出现则返回 true。

class Person {}

const p1 = new Person();

if (p1 instanceof Person) {
  console.log('✅ is instance of Person');
} else {
  console.log('⛔️ is not instance of Person');
}

class Animal {}
console.log(p1 instanceof Animal); // ?️ false

instanceof 运算符返回一个布尔值,表示构造函数的原型属性是否出现在对象的原型链中。

instanceof 运算符在 TypeScript 中非常有用,因为它可以用作类型保护。

class Person {
  walk() {
    console.log('person is walking');
  }
}
class Animal {
  run() {
    console.log('animal is running');
  }
}

function example(x: Person | Animal) {
  // ?️ x is type Person or Animal here
  if (x instanceof Person) {
    // ?️ x is type Person here
    x.walk();
  } else {
    // ?️ x is type Animal here
    x.run();
  }
}

该函数采用 Person 或 Animal 类型的参数,因此在我们访问特定于类的方法之前,我们必须检查传递给该函数的类的实例。

如果访问 constructor.name 属性,可以看到 p1 对象的类名是 Person。

class Person {}

const p1 = new Person();

console.log(p1.constructor.name); // ?️ Person

我们访问了 Object.constructor 属性上的 name 属性。

instanceof 运算符检查对象原型链中是否存在 constructor.prototype。

class Person {}

const p1 = new Person();

// ?️ true
console.log(Object.getPrototypeOf(p1) === Person.prototype);
class Person {}
class Animal {}

const person = new Person();

if (!(person instanceof Animal)) {
  console.log('person is NOT an instance of Animal');
}

一个常见的错误是省略括号,例如:

class Person {}
class Animal {}

const person = new Person();

// ?️ Don't do this

// ⛔️ Error: The left-hand side of an 'instanceof'
// expression must be of type 'any', an object type
// or a type parameter.ts(2358)
if (!person instanceof Animal) {
  console.log('person is NOT an instance of Animal');
}

此代码示例反转对象的值并将其转换为布尔值,因此它变为 false。 然后我们检查 false 是否是 Animal 类的实例。

如果不喜欢括号方法,我们可以显式检查 instanceof 运算符是否返回 false。

class Person {}
class Animal {}

const person = new Person();

if (person instanceof Animal === false) {
  console.log('person is NOT an instance of Animal');
}

这实现了与使用带括号的逻辑 NOT ! 运算符相同的目标,但更易于阅读。