理解 TypeScript 中 type 和 interface 的区别

1,267 阅读2分钟

TypeScript 是 JavaScript 的超集,提供了强大的类型检查功能,帮助开发者编写更安全、更易维护的代码。其中,type 类型别名和 interface 接口声明是定义自定义类型的两种常用方式。它们看起来很相似,但实际上在设计目的和使用场景上有所不同。本文将介绍它们的主要区别、相似之处以及最佳实践。


什么是 type

type 是类型别名,它可以为任意合法的 TypeScript 类型命名,包括基本类型、联合类型、元组,甚至接口。

type Point = {
  x: number;
  y: number;
};

type ID = string | number;

type 非常灵活,能够表示复杂的类型结构,例如联合类型和交叉类型:

type Shape = Circle | Rectangle;

type Circle = { kind: "circle"; radius: number };
type Rectangle = { kind: "rectangle"; width: number; height: number };

什么是 interface

interface 用于定义对象的结构,主要用于描述类的契约,或可扩展的对象类型。

interface Point {
  x: number;
  y: number;
}

接口支持 声明合并(declaration merging),也就是说你可以多次声明同一个接口,TypeScript 会自动将它们合并:

interface Person {
  name: string;
}

interface Person {
  age: number;
}

// 合并后,Person 包含 name 和 age 属性
const user: Person = { name: "Alice", age: 30 };

核心区别对比

特性type 类型别名interface 接口
能否描述原始类型或联合类型✅ 可以❌ 不可以
能否定义元组✅ 可以❌ 不可以
是否支持声明合并❌ 不支持✅ 支持
能否扩展其他类型✅ 使用 &(交叉类型)✅ 使用 extends
能否被类实现(implements)✅ 可以✅ 可以
是否推荐用于对象类型✅ 推荐(灵活)✅ 推荐(尤其是公开 API)

何时使用 typeinterface

  • 使用 interface 的场景:

    • 定义对象的结构。
    • 与类结合使用,定义接口契约。
    • 希望接口可以被扩展或合并。
    • 编写公开的 API 时。
  • 使用 type 的场景:

    • 需要使用联合类型或交叉类型组合。
    • 定义基本类型、元组或复杂组合类型。
    • 喜欢函数式、组合式的类型风格。

实际示例

// 使用 interface 定义对象结构
interface User {
  id: number;
  name: string;
}

// 使用 type 定义交叉类型
type Admin = User & {
  role: "admin";
};

// 使用 type 定义联合类型
type Status = "pending" | "active" | "disabled";

总结

typeinterface 都是 TypeScript 中定义类型的强大工具。一般来说:

  • 对于公开的对象类型结构或面向类的设计,推荐使用 interface
  • 对于更复杂的类型组合,例如联合、交叉、元组等结构,推荐使用 type

掌握这两者的差异和使用时机,将帮助你编写更清晰、表达力更强的 TypeScript 代码。