interface 和 type 的区别,一文彻底搞懂!

309 阅读2分钟

首先,我需要回顾一下这两个概念的基本定义和用途,在 TypeScript 中,interface 和 type 都用于定义类型,但它们在设计目的、使用场景和特性上有一些关键区别。以下是它们的核心差异:

1. 核心设计目的

interface
专门用于定义对象类型(Object Shape),强调描述对象的结构(如属性、方法等)。
例如:

interface User {
  name: string;
  age: number;
}

type
类型别名(Type Alias),可以为任何类型(包括原始类型、联合类型、元组等)定义别名,更灵活。
例如:

type ID = string | number;       // 联合类型
type Point = [number, number];   // 元组
type Callback = () => void;      // 函数类型

2. 扩展能力

interface
支持声明合并(Declaration Merging):多次声明同名 interface 会自动合并。

interface User { name: string; }
interface User { age: number; }
// 合并为 { name: string; age: number; }

type
不支持声明合并:重复定义同名 type 会报错。

type User = { name: string; };
type User = { age: number; }; // Error: Duplicate identifier 'User'

3. 继承方式

  • interface
    使用 extends 关键字直接继承其他 interface 或 type
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }

type
使用交叉类型(&)实现类似继承的效果:

type Animal = { name: string; };
type Dog = Animal & { breed: string; };

4. 实现(Implements)

  • interface
    类可以直接通过 implements 实现一个 interface
interface Vehicle { move(): void; }
class Car implements Vehicle { move() { /* ... */ } }

type
只有当 type 定义的是对象类型时,类才能实现它(但无法实现联合类型等复杂类型):

type Vehicle = { move(): void; };
class Car implements Vehicle { move() { /* ... */ } } // 允许

5. 灵活性

  • interface
    只能描述对象类型,无法直接定义联合类型、交叉类型或元组等。
    例如,无法直接这样写:
interface MyType = string | number; // Error

type
可以定义任意复杂类型,包括联合类型、交叉类型、映射类型等:

type StringOrNumber = string | number;          // 联合类型
type ReadonlyUser = Readonly<User>;             // 映射类型
type PartialUser = Partial<User>;               // 映射类型
type Tuple = [string, number];                  // 元组
type Keys = keyof User;                         // 索引类型查询

6. 性能与工具提示

  • interface
    在合并同名接口时,IDE 的智能提示会显示合并后的完整结构。
    例如:
interface User { name: string; }
interface User { age: number; }
const user: User = { /* 提示 name 和 age */ };

type
当使用复杂类型(如联合类型)时,IDE 提示可能显示类型别名本身而非展开后的内容:

type MyType = string | number;
const value: MyType = /* 提示为 MyType,而非 string | number */;

7. 最佳实践

场景推荐使用
定义对象类型(如组件 Props)interface
需要声明合并(如扩展第三方库)interface
联合类型、交叉类型、元组type
函数类型、复杂类型操作type

总结

  • 优先使用 interface
    当需要定义对象类型,且可能需要扩展或通过类实现时。
  • 使用 type
    当需要定义联合类型、交叉类型、元组或复杂类型操作时。

两者并非完全互斥,实际项目中可以结合使用,根据场景选择最合适的工具。