ts 中 type 和 interface的共同点和区别

287 阅读3分钟

type 与 interface 的区别与共同点

共同点:

  1. 类型定义:两者都可以用来定义对象类型
// 使用 interface
interface PersonInterface {
  name: string;
  age: number;
}

// 使用 type
type PersonType = {
  name: string;
  age: number;
};
  1. 函数类型定义:两者都可以定义函数类型
// 使用 interface
interface SearchFunc {
  (source: string, subString: string): boolean;
}

// 使用 type
type SearchFunc = (source: string, subString: string) => boolean;
  1. 扩展能力:两者都可以被扩展(但语法不同)
// interface 扩展 interface
interface EmployeeInterface extends PersonInterface {
  employeeId: string;
}

// type 扩展 type
type EmployeeType = PersonType & {
  employeeId: string;
};

// interface 扩展 type
interface EmployeeInterface2 extends PersonType {
  department: string;
}

// type 扩展 interface
type EmployeeType2 = PersonInterface & {
  position: string;
};

主要区别:

特性interfacetype
声明合并✅ 支持同名接口自动合并❌ 不允许重复声明
扩展语法extends 关键字& 交叉类型
描述范围对象/函数类型任意类型(联合、元组、基本类型等)
实现类class X implements Y仅支持对象类型
元组类型❌ 不支持✅ 支持 type Coord = [number, number]
联合类型❌ 不支持✅ 支持 `type ID = stringnumber`
映射类型❌ 不支持✅ 支持 type Readonly<T> = { readonly [P in keyof T]: T[P] }
错误提示显示接口名称展开具体类型

声明合并示例:

interface User {
  name: string;
}

interface User {
  age: number;
}

// 合并为 { name: string; age: number; }
const user: User = {
  name: "Alice",
  age: 30
};

最佳实践:

  • 使用 interface 定义对象类型和类契约
  • 使用 type 定义联合类型、元组或复杂类型操作
  • 在公共 API 定义时优先使用 interface(更清晰的错误提示)

交叉类型 (Intersection Types)

交叉类型是将多个类型合并为一个类型,用 & 运算符表示

type Employee = {
  id: number;
  name: string;
};

type Manager = {
  department: string;
  manage(): void;
};

// 交叉类型
type ManagerEmployee = Employee & Manager;

const boss: ManagerEmployee = {
  id: 1,
  name: "Alice",
  department: "Engineering",
  manage() {
    console.log("Managing team");
  }
};

关键特点:

  1. 类型组合:合并多个类型的属性
  2. 冲突处理:同名属性会合并为交集类型
type A = { value: number; common: string };
type B = { value: string; common: number };

type C = A & B;
// value 成为 never 类型 (number & string)
// common 成为 never 类型 (string & number)
  1. 与接口继承区别

    • 接口继承:extends 是子集关系
    • 交叉类型:& 是集合的交集操作

联合类型 (Union Types)

联合类型表示一个值可以是几种类型之一,用 | 运算符表示

type ID = string | number;
type Status = "active" | "inactive" | "pending";

类型守卫 (Type Guards):

处理联合类型时需要缩小类型范围

function printID(id: ID) {
  if (typeof id === "string") {
    // 此处 id 被识别为 string
    console.log(id.toUpperCase());
  } else {
    // 此处 id 被识别为 number
    console.log(id.toFixed(2));
  }
}

可辨识联合 (Discriminated Unions):

使用共同字段区分联合类型

type Circle = {
  kind: "circle";
  radius: number;
};

type Square = {
  kind: "square";
  sideLength: number;
};

type Shape = Circle | Square;

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
  }
}

联合类型 vs 交叉类型:


联合类型 vs 交叉类型:

含义: 类型A **或** 类型B | 类型A **且** 类型B 

使用场景: 值可能是多种类型之一 | 值必须同时满足多个类型 

示例:`string | number` | `Employee & Manager` 

类型收缩:需要类型守卫确定具体类型 | 直接包含所有类型的属性

空值处理: 常与 `null` 或 `undefined` 使用 | 不兼容包含 `null` 的类型 


// 联合类型示例:可能是字符串或数字数组
type StringOrNumberArray = string[] | number[];

// 交叉类型示例:同时拥有两种类型的所有属性
type Named = { name: string };
type Aged = { age: number };
type Person = Named & Aged;

总结图

TypeScript 类型系统
├── 类型定义
│   ├── interface → 对象类型(支持声明合并)
│   └── type → 任意类型(支持高级类型操作)
│
├── 类型组合
│   ├── 联合类型 (A | B) → "或"关系
│   │   └── 需类型守卫缩小范围
│   │
│   └── 交叉类型 (A & B) → "与"关系
│       └── 合并多个类型属性
│
└── 类型操作
    ├── keyof → 获取对象键的联合类型
    ├── typeof → 获取值的类型
    └── 条件类型 → T extends U ? X : Y

理解这些核心概念对于掌握 TypeScript 至关重要,特别是在大型项目中保持类型安全和代码可维护性。