文章目录

TypeScript 接口:interface 与 type 的区别

发布于 2026-04-16 14:23:30 · 浏览 13 次 · 评论 0 条

TypeScript 接口:interface 与 type 的区别

在 TypeScript 项目中,定义数据结构时常常面临一个选择:使用 interface 还是 type。虽然两者在许多情况下表现相似,但在底层机制、扩展能力和适用场景上存在显著差异。掌握这些区别,有助于编写更规范、更易维护的代码。


1. 定义基础对象结构

对于最普通的对象定义,两者在语法和最终生成的类型检查上几乎完全一致。

执行以下代码分别定义一个用户对象:

// 使用 interface 定义
interface UserInterface {
  id: number;
  name: string;
}

// 使用 type 定义
type UserType = {
  id: number;
  name: string;
};

在使用层面,这两种定义方式没有任何区别。你可以互换地使用 UserInterfaceUserType 来声明变量。在此场景下,选择哪一种主要取决于团队或项目的代码风格偏好。


2. 处理联合类型、交叉类型与基本类型别名

这是 type 关键字最核心的优势领域。interface 只能用于定义对象的结构,而 type 可以给任意类型起别名,包括基本类型、联合类型、元组等。

使用 type 定义一个联合类型,表示 ID 可以是数字或字符串:

type ID = number | string;

// 尝试用 interface 定义会报错
// interface ID = number | string; // Error

使用 type 定义一个元组类型,精确规定数组元素的顺序和类型:

type Coordinate = [number, number];

const point: Coordinate = [100, 200];

记住:当你需要处理非对象类型(如 string | number)、工具类型(如 Partial)或复杂的类型组合时,必须 使用 type


3. 继承与扩展的方式

虽然两者都可以实现类型的扩展,但语法和底层逻辑不同。

使用 extends 关键字interface 继承另一个 interface

interface Animal {
  name: string;
}

interface Bear extends Animal {
  honey: boolean;
}

使用 交叉类型(&扩展 type

type Animal = {
  name: string;
};

type Bear = Animal & {
  honey: boolean;
};

这里有一个关键的互通性:interface 可以继承 type(只要该 type 是对象类型),type 也可以交叉 interface

注意,当处理同名属性冲突时,两者的行为不同:

  • interface 继承时,如果属性类型不兼容,会直接报错。
  • type 交叉时,属性类型会进行交叉运算(对于基础类型,通常会导致 never 类型,因为一个值不可能既是 string 又是 number)。

4. 声明合并

这是 interface 独有的特性,也是区分使用场景的重要依据。同名 interface 会自动合并为一个定义,而同名 type 会直接报错。

定义两个同名的 interface

interface Window {
  title: string;
}

interface Window {
  status: string;
}

TypeScript 会自动将其合并为:

interface Window {
  title: string;
  status: string;
}

尝试type 做同样的操作:

type Window = {
  title: string;
};

// Error: Duplicate identifier 'Window'
type Window = {
  status: string;
};

应用场景:当你需要扩展第三方库或全局对象(如 WindowDocument 或全局 CSS 模块)的类型定义时,必须 使用 interface 进行声明合并。


5. 映射类型的性能表现

在处理复杂的映射类型(如使用 RecordPickOmit 等工具类型)时,type 通常是首选。

定义一个复杂的映射类型:

type Keys = 'name' | 'age';
type Person = {
  [K in Keys]: string;
};

虽然 interface 可以通过 Record 工具间接实现类似功能,但在处理动态键值对或复杂的类型体操时,type 的语法更加直观且功能更强大。大型类型计算库(如 utility-types)通常都基于 type 构建,因为 type 能够构建更复杂的类型图。


6. 决策流程图

为了在实际开发中快速做出判断,请遵循以下逻辑:

graph TD A[开始: 定义类型] --> B{是否为非对象类型?} B -- 是 --> C[使用 type] B -- 否 --> D{是否需要声明合并?} D -- 是 --> E[使用 interface] D -- 否 --> F{主要用途是 OOP 设计\n还是类型组合?} F -- OOP / 对象扩展 --> G[倾向使用 interface] F -- 联合 / 元组 / 映射 --> H[使用 type]

7. 核心差异对比表

下表总结了两者在关键维度上的区别:

特性 interface type
定义对象 支持 支持
定义联合/元组 不支持 支持
基本类型别名 不支持 支持
继承方式 extends 交叉类型 &
声明合并 支持 不支持
计算属性/映射 较弱 强大

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文