基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

TypeScript interface 和 type 有什么区别?

知识点图片

在 TypeScript 中,interface(接口)和 type(类型别名)非常相似,在许多情况下可以互换使用。但在现代 TypeScript(尤其是 4.x/5.x 版本)中,它们的区别主要集中在扩展性表达能力语义上。

以下是详细的对比总结:

核心区别速览

特性 Interface (接口) Type (类型别名)
定义对象/函数 ✅ 支持 ✅ 支持
声明合并 (Declaration Merging) 支持 (自动合并) ❌ 不支持 (报错重复定义)
联合类型 (Union Types) ❌ 不支持 支持 (A | B)
基本类型别名 ❌ 不支持 支持 (type Name = string)
元组 (Tuple) ❌ 语法繁琐 支持 ([string, number])
扩展方式 使用 extends 关键字 使用 & (交叉类型)
映射类型 (Mapped Types) ❌ 不支持 支持 (in keyof)
主要用途 定义对象结构、类契约、库的扩展 定义联合类型、工具类型、复杂组合

详细区别解析

1. 声明合并 (Declaration Merging) —— 最重要的区别

这是 interface 独有的特性。如果你定义了两个同名的 interface,TypeScript 会自动把它们合并成一个。

  • Interface:

    typescript
    interface User {
      name: string;
    }
    
    interface User {
      age: number;
    }
    
    // 结果:User 包含 name 和 age
    const user: User = {
      name: "Alice",
      age: 18
    };

    应用场景: 这对于扩展第三方库(如向 Window 对象添加属性)非常重要。

  • Type:

    typescript
    type User = {
      name: string;
    };
    
    // 报错:Duplicate identifier 'User'.
    type User = {
      age: number;
    };

2. 类型表达能力 (Type Capabilities)

type 的表达能力更强,它可以定义非对象类型。

  • 基本类型别名:
    typescript
    type ID = string; // interface 做不到
  • 联合类型 (Union Types):
    typescript
    type Status = "success" | "error" | "loading"; // interface 做不到
  • 元组 (Tuples):
    typescript
    type Point = [number, number]; // interface 做不到这么简洁

3. 扩展方式 (Extensibility)

两者都可以扩展,但语法不同。

  • Interface 使用 extends (更具面向对象语义):

    typescript
    interface Animal {
      name: string;
    }
    interface Bear extends Animal {
      honey: boolean;
    }
  • Type 使用 & (交叉类型):

    typescript
    type Animal = {
      name: string;
    };
    type Bear = Animal & {
      honey: boolean;
    };

    注意:Interface 也可以 extends 一个 Type(只要该 Type 是对象结构),Type 也可以 & 一个 Interface。

4. 映射类型 (Mapped Types)

如果你需要遍历键来生成新类型,必须使用 type

typescript
type Keys = "firstName" | "lastName";
type DuplicateMap = {
  [K in Keys]: string;
};
// interface 无法直接使用 in keyof 语法

5. 错误提示与性能 (微小差异)

  • Interface: 创建了一个新的名字。在报错时,通常会直接显示接口名称(如 User)。
  • Type: 只是一个别名。在某些复杂的交叉类型或联合类型中,报错时可能会把具体的结构展开显示,而不是显示别名(不过新版 TS 在这方面优化了很多)。
  • 性能: 官方曾提到 interface 的类型检查性能略优于交叉类型 (type&),因为接口可以缓存属性关系,但这通常只在巨型项目中才有感知。

最佳实践:该用哪个?

虽然没有绝对的标准,但社区和官方通常建议如下:

  1. 优先使用 interface 定义对象结构:

    • 如果你是在定义一个对象(Object)的形状。
    • 如果你是在编写库(Library)或公共 API,因为使用者可能需要通过声明合并来扩展你的接口。
    • 如果你在使用面向对象编程(Class implements)。
  2. 在以下情况使用 type

    • 定义联合类型(如 type ID = string | number)。
    • 定义基本类型的别名。
    • 定义元组
    • 使用高级类型功能(如映射类型、条件类型、提取类型等工具类型)。
    • 定义 React 组件的 Props 时,现在社区中 typeinterface 混用,但使用 type 略多一些,因为它处理联合类型更方便。

简单总结口诀:

"对象结构用 Interface,复杂组合与别名用 Type,库的公开类型必须用 Interface。"

00:00
00:00