TypeScript 中 type 和 interface 的选择

摘要:很多人在用 TypeScript 时,会纠结该用 type 还是 interface。这两种方式都能定义类型,但在实际使用中各有特点。这篇文章会帮你弄清楚它们的区别,让你能在不同情况下做出合适的选择。

很多人在用 TypeScript 时,会纠结该用 type 还是 interface。这两种方式都能定义类型,但在实际使用中各有特点。这篇文章会帮你弄清楚它们的区别,让你能在不同情况下做出合适的选择。


基本用法

先来看一个简单的例子。我们可以用 type 来定义一个“人”的类型:

type Person = {
  name: string;
  age: number;
}

也可以用 interface 来定义:

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

表面上看,这两种方式的效果差不多。type 需要用等号来赋值,interface 则是直接声明。不过,它们的区别远不止这些。


扩展方式

有人说 interface 在扩展方面更自然,因为它可以用 extends 关键字:

interface Job {
  job: string;
}

interface Person extends Job {
  name: string;
  age: number;
}

type 也能扩展,用的是交叉类型 &:

type Person = {
  name: string;
  age: number;
} & { job: string };

type 还支持联合类型,这是 interface 做不到的:

type Status = 'success' | 'error';

如果你喜欢把类型像积木一样组合起来,type 给你更多灵活性。


在类中的使用

如果你用面向对象的方式写代码,interface 可以和 class 配合得更好:

interface Work {
  doWork: () => void;
}

class Person implements Work {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  doWork() {
    console.log('Working...');
  }
}

type 不能直接被类实现。所以,如果你的代码里有很多 class 和 implements,interface 会更方便。


性能考虑

有人担心 type 和 interface 在编译速度上有差异。实际上,TypeScript 团队和社区专家都确认过,这两种方式在类型检查性能上没有明显差别。你不需要因为这个因素而纠结选哪个。


需要注意的问题

interface 有一个特殊功能叫“声明合并”。意思是,如果你定义了同名的 interface,TypeScript 会自动把它们合并:

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

interface Person {
  gender: string;
}

// 最终 Person 类型包含 name、age 和 gender

这个功能在某些时候很有用,比如你想给第三方库的类型添加字段:

// 扩展第三方库的类型
declare module 'some-library' {
  interface Config {
    customField: string;
  }
}

但在日常开发中,这个特性可能带来问题。如果不同文件里都有同名的 interface,它们会被合并,这可能让你意料不到。特别是当项目变大时,这种隐式的合并会让代码更难维护。

type 没有这个功能,同一个 type 不能重复声明,所以更可控。


如何选择

根据上面的分析,我们可以得出一些实用的建议:

用 interface 的情况:

  • 需要类来实现接口时

  • 要扩展第三方库的类型时

  • 团队习惯用 interface 并且代码风格统一

用 type 的情况:

  • 需要组合多种类型,比如用联合类型或交叉类型时

  • 想要更直观的类型定义,避免意外的合并

  • 大部分日常的类型定义


实际例子

假设你在开发一个用户管理系统,可以这样组合类型:

// 用 type 组合多种类型
type ID = string | number;
type User = {
  id: ID;
  name: string;
} & Partial<{
  email: string;
  phone: string;
}>;

// 用 interface 定义需要实现的契约
interface Validatable {
  validate: () => boolean;
}

class UserModel implements Validatable {
  constructor(public id: ID, public name: string) {}

  validate() {
    return this.name.length > 0;
  }
}


总结

选择 type 还是 interface,主要看具体需求。interface 在面向对象编程和扩展第三方类型时更有优势。type 在类型组合和代码可维护性上更胜一筹。

对于大多数日常开发场景,type 是更安全的选择。它没有隐藏的合并行为,表达方式更灵活,能让代码更清晰易懂。不过,最重要的还是保持项目中的一致性,确保整个团队使用相同的规范。

无论选择哪种方式,理解它们的特性和适用场景,都能帮助你写出更健壮、更易维护的 TypeScript 代码。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_13019