编程前端开发者

TypeScript 中的联合类型机制是如何工作的?它有什么用处,如何进行类型细化,以及使用联合类型时有哪些注意事项?

用 Hintsage AI 助手通过面试

答案。

问题的历史:

联合类型在 TypeScript 中出现,旨在描述可以接受多种类型值的变量和参数。这一功能大大增强了与经典语言相比的类型灵活性。

问题:

在 JavaScript 中,函数和变量通常是多格式的(例如,可以接受数字或字符串),这使得安全类型化变得复杂。如果没有联合类型,只能使用 any 或重复代码。这增加了生产环境中的错误数量,并使大团队的工作变得困难。

解决方案:

联合类型允许声明一个可以是多种类型之一的变量,在检查后保证执行正确的操作。同时,实现了类型细化(type narrowing)的支持,这有助于编译器“理解”它所处理的内容。

代码示例:

function formatId(id: number | string): string { if (typeof id === 'string') { return id.toUpperCase(); } return id.toString(); }

关键特点:

  • 允许明确指示变量和参数的可能类型。
  • 与通过检查(例如,typeof 或 in)进行的类型细化机制一起工作。
  • 增加了对具有不同类型的相同键的对象的处理复杂性——需要谨慎管理访问逻辑。

带陷阱的问题。

可以写一个包含不同属性对象的联合类型,并在不检查的情况下访问任何属性吗?

不可以。联合类型只能访问所有类型中都存在的属性和方法。要访问特定属性,需要进行类型细化。

代码示例:

type Fish = { swim: () => void; }; type Bird = { fly: () => void; }; function move(animal: Fish | Bird) { // animal.swim(); // 没有细化引发错误 if ('swim' in animal) { animal.swim(); // 好 } }

为什么字符串 | 数字的联合类型并非所有方法都可用?

TypeScript 在联合中只允许存在于所有包含类型中的内容。对于个别方法,需要先检查实际类型。

如果不检查联合类型的类型,而尝试调用特定方法,会发生什么?

在这种情况下,将出现编译错误,因为无法保证该方法的存在。只有在检查特定类型后才能使用。

常见错误和反模式

  • 在使用前跳过类型检查(可能导致访问错误)。
  • 描述过于宽泛的联合类型(将失去类型安全性)。
  • 不正确的细化导致隐性错误和未穷尽的检查。

生活中的示例

负面案例

给变量类型 string | number,未检查就进行了 toUpperCase()。结果应用程序在数字数据上崩溃。

优点:

  • 快速编写的代码。

缺点:

  • 运行时错误。
  • 对 TypeScript 静态类型的失去信任。

正面案例

在使用方法前检查类型:

if (typeof value === 'string') { return value.toUpperCase(); } else { return value.toString(); }

优点:

  • 在编译阶段的完全安全性。
  • 提高了代码的可维护性。

缺点:

  • 需要编写额外的检查。