编程全栈开发员

如何使用类型扩展(extends),与类型和接口的使用有什么细节,这对项目结构有何影响?

用 Hintsage AI 助手通过面试

答案

在 TypeScript 中,可以通过 interface extendstype & type(交叉类型)来扩展(继承)类型。接口也可以扩展类型,反之亦然。

接口使用关键字 extends 来继承属性:

interface Animal { name: string; } interface Bird extends Animal { wings: number; }

类型可以通过 & 来组合:

type Animal = { name: string }; type Bird = Animal & { wings: number };

另外,接口可以扩展另一个类型:

type Base = { id: number }; interface Derived extends Base { description: string; }

特点:

  • 接口支持声明合并(declaration merging),而类型不支持。
  • 如果预期要扩展其他实体(例如,用于库),建议使用接口。
  • 嵌套的 extends 可能导致复杂的层次结构,增加维护难度并产生名称冲突。

误导性问题

可以通过接口扩展类型,或者反过来吗?大多数人犯了什么错误?

许多人认为只能通过接口扩展接口,但实际上,接口可以扩展类型:

type Basic = { flag: boolean }; interface Extra extends Basic { name: string; }

但类型不能通过 extends 扩展其他类型 — 只能通过交叉类型(&)。

由于不知道主题细节而导致的真实错误示例


故事

在一个大型项目中,通过 extends 合并接口,忘记了同名属性的类型必须一致。当有人修改父接口中属性的类型时,子接口中出现了静默冲突,数据库不再符合 API。

故事

在库中编写了类型别名,通过 &(交叉)覆盖属性,但某些属性在类型上不兼容。TypeScript 在编译阶段跳过了这一点,但实际上在运行时系统中出现了未定义的字段。

故事

团队认为接口不能通过类型扩展,因此为了扩展通用功能,重写了所有结构,从 type 变为 interface,花费了大量时间和精力 — 而实际上可以以非标准方式扩展现有类型。