TypeScript 中的类类型检查:如何检查对象的类型

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何在 TypeScript 中检查类类型:从新手到专家

\n\n

你是否曾经在 TypeScript 中编写代码,收到一个未知类型的对象,然后想:“你到底是什么?”?这个问题困扰着成千上万的开发者——难怪 TypeScript 中的类类型检查 这个话题在 Stack Overflow 上获得了数十万的浏览量。今天,我们将一劳永逸地弄清楚如何在 TypeScript 中正确检查类类型。

\n\n

在本文中,你将了解:

\n
    \n
  • 为什么 typeof 不适用于类
  • \n
  • 如何像使用瑞士军刀一样使用 instanceof
  • \n
  • 什么是类型守卫以及它们如何拯救你的代码
  • \n
  • 如何使用 is 编写你自己的类型检查
  • \n
  • 来自实践的真实示例
  • \n
\n\n

我们开始吧!

\n\n

问题:为什么 typeof 在这里无能为力?

\n\n

在 JavaScript 中,有一个 typeof 运算符,它对于原始类型非常有效:

\n\n
typeof "hello" // "string"\ntypeof 42      // "number"\ntypeof true    // "boolean"
\n\n

但是当涉及到类时,typeof 就失效了:

\n\n
class Dog {}\nclass Cat {}\n\nconst pet = new Dog();\n\ntypeof pet; // "object" — 毫无用处!\ntypeof Dog; // "function" — 也不是我们想要的
\n\n

为什么?因为 JavaScript 中的类只是构造函数函数的语法糖。typeof 只能看到“对象”或“函数”,但无法区分它 具体是哪个 类。

\n\n

这时,TypeScript 中的类类型检查 就登场了——这是一整套工具,可以帮助你精确地确定你正在处理的是哪个类的实例。

\n\n

方法 1:instanceof —— 你的主要助手

\n\n

检查类类型最直接、最清晰的方法是使用 instanceof 运算符。它检查该类是否存在于对象的原型链中:

\n\n
class Animal {\n  name: string;\n  constructor(name: string) {\n    this.name = name;\n  }\n}\n\nclass Dog extends Animal {\n  bark() {\n    console.log("Woof!");\n  }\n}\n\nclass Cat extends Animal {\n  meow() {\n    console.log("Meow!");\n  }\n}\n\nfunction handleAnimal(animal: Animal) {\n  if (animal instanceof Dog) {\n    // TypeScript 知道 animal 是 Dog 类型\n    animal.bark();\n  } else if (animal instanceof Cat) {\n    animal.meow();\n  } else {\n    console.log(`Unknown animal: ${animal.name}`);\n  }\n}\n\nconst rex = new Dog("Rex");\nhandleAnimal(rex); // "Woof!"
\n\n

请注意:在检查 animal instanceof Dog 之后,TypeScript 会自动收窄类型(类型收窄),并允许你调用 Dog 的方法而不会出错。这就是 类型守卫 的魔力——内置的类型保护者。

\n\n

什么时候 instanceof 不起作用?

\n
    \n
  • 处理不同的窗口/框架时(不同的全局对象)
  • \n
  • 如果类定义在不同模块且版本不同时
  • \n
  • 检查接口时(接口在运行时不存在)
  • \n
\n\n

方法 2:使用 is 运算符创建自定义类型守卫

\n\n

有时 instanceof 还不够。例如,你可能不仅想检查类,还想检查额外的条件。这时,使用 is 关键字的用户自定义类型守卫就派上用场了:

\n\n
interface Bird {\n  fly(): void;\n  layEggs(): void;\n}\n\ninterface Fish {\n  swim(): void;\n  layEggs(): void;\n}\n\nfunction isFish(pet: Bird | Fish): pet is Fish {\n  return (pet as Fish).swim !== undefined;\n}\n\nfunction move(pet: Bird | Fish) {\n  if (isFish(pet)) {\n    // TypeScript 知道:pet 是 Fish 类型\n    pet.swim();\n  } else {\n    pet.fly();\n  }\n}
\n\n

请注意返回类型中的语法:pet is Fish。这告诉 TypeScript:“如果这个函数返回 true,那么参数 pet 就是 Fish 类型”。现在,只要你使用

博客

书籍推荐