文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载本指南聚焦 TypeScript 中扩展已有类型以派生新类型这一核心能力系统讲解interface extends继承、多接口继承、type的交叉组合以及 interface 与 type 之间扩展方向的单向限制。学完本文你将能在日常开发中根据对象结构复用与类型组合变换两种诉求正确选择extends或并理解二者在结构性类型系统下的底层差异。一、从一个核心问题说起为什么扩展类型值得单独成章在 TypeScript 中几乎每个真实项目都会遇到这样的需求已经定义好一个领域模型如User现在需要派生一个更具体的形态如AdminUser既想复用原有字段又想追加新字段。面对这个需求开发者往往会在两条路径之间犹豫用interface B extends A { ... }声明继承用type B A { ... }做交叉组合。《The Concise TypeScript Book》本仓库的核心书籍见 目录在第 16 节 Extending Types 中用最小但完整的代码集回答了这一问题。本文以此节为骨架结合仓库中 Intersection Types、Merging and Extension、Differences between Type and Interface 等相邻章节做一次纵深拆解。二、interface 扩展用 extends 复制成员2.1 单接口继承扩展一个interface本质是从另一个类型复制成员到新类型中。原书给出了最基础的形态interface X { a: string; } interface Y extends X { b: string; }此时Y同时拥有a: string与b: string两个成员。基于结构类型系统任何满足Y形状的对象都可以被赋给Yconst obj: Y { a: hello, b: world, };这与仓库中 Merging and Extension 的定义一致扩展Extension指从既有类型或接口继承以创建新类型是在不修改原始定义的前提下为既有类型追加属性或方法的机制。2.2 多接口继承extends A, Bextends关键字支持一次继承多个接口用逗号分隔interface A { a: string; } interface B { b: string; } interface Y extends A, B { y: string; }由此派生的Y必须同时满足A、B以及自身的全部成员约束const obj: Y { a: aa, b: bb, y: yy, };这一点与类的继承形成鲜明对比TypeScript 的类只允许单一基类继承不支持传统意义上的多重继承但接口可以继承多个接口详见 Class 的 Inheritance 一节。多接口继承让组合出复合契约成为可能——例如一个Flyable与Swimmable的并集契约可以被interface FlyingFish extends Flyable, Swimmable {}一次性描述。2.3 interface 与 class 的 extends 一致性书中强调extends关键字只作用于接口和类。这意味着你在接口继承中获得的经验可以平滑迁移到类继承class Animal { name: string; constructor(name: string) { this.name name; } speak(): void { console.log(The animal makes a sound); } } class Dog extends Animal { breed: string; constructor(name: string, breed: string) { super(name); this.breed breed; } speak(): void { console.log(Woof! Woof!); } }在接口与类的双重视角下extends语义是统一的派生方获得基方的全部公开成员并可在此基础上扩展或重写override。三、type 的扩展方式交叉类型 当要扩展的对象是用type关键字声明的尤其是类型别名extends不再适用必须改用交叉类型运算符type A { a: number; }; type B { b: number; }; type C A B;交叉类型C表示同时具有A与B所有属性的值。这正是仓库 Intersection Types 的定义交叉类型代表一个同时拥有两个或多个类型全部属性的值用连接各类型type X { a: string; }; type Y { b: string; }; type J X Y; // Intersection const j: J { a: a, b: b, };在 Interface and Type 与 Type Manipulation 中交叉类型同样被列为从类型创建类型的第一手段type A { foo: number }; type B { bar: string }; type C A B; // Intersection of A and B const obj: C { foo: 42, bar: hello };3.1 交叉类型与接口继承的本质区别两者虽然都能合并成员但机制不同接口继承interface B extends A是声明继承B是继承自 A 的新接口可继续被其它接口继承、可参与后续的声明合并。交叉类型type C A B是类型组合C是一个由A与B合并而成的新类型它本身是type别名无法再次用extends继承也无法参与声明合并。从语义上讲接口继承更接近面向对象中的is-a关系交叉类型更接近同时满足多个结构约束。选择哪种取决于你是否还需要对合并结果做进一步的接口化操作。3.2 交叉类型的组合自由度交叉类型的好处是组合对象不限于对象字面量形状任何类型都可以参与。书中 Differences between Type and Interface 展示了它与联合类型|配合的典型场景type Department dep-x | dep-y; // Union type Person { name: string; age: number; }; type Employee { id: number; department: Department; }; type EmployeeInfo Person Employee; // Intersection这里EmployeeInfo一次性继承了Person的两个字段与Employee的两个字段同时保留了Department的字面量联合约束——这是接口继承难以直接表达的复杂类型组合。四、interface 扩展 type单向的 extends书中最后一条规则最容易踩坑可以用 interface 扩展 type但不能反过来用 type 扩展 interface。正向是合法的type A { a: string; }; interface B extends A { b: string; }由于 TypeScript 是结构化类型系统type A { a: string }与interface A { a: string }在成员层面等价因此接口继承一个类型别名是允许的。但反过来——type B A extends interface——并不存在这种语法type 一侧只能用组合。仓库 Erased Structural Types 也印证了这一判断的前提在 TypeScript 中对象并不需要匹配某个精确的、唯一的类型声明只要一个对象满足了某个接口的全部要求它就可以被用于需要该接口的位置即便两者之间没有任何显式关联。正是这种形状即类型的模型让interface extends type得以成立。4.1 为什么方向是不对称的方向不对称的根源在于两种声明的能力差异interface声明的是开放的、可扩展的契约天然支持extends语法type别名本质是给一个类型表达式起名字没有声明式继承语法扩展只能通过在表达式中完成。因此当你有一个type作为基础形状、又想让它成为一个可被其它接口继承的契约时直接写interface B extends A即可而当你持有interface、想生成一个组合类型时则把接口放进type的表达式中这正是 Differences between Type and Interface 中type B A { j: string }的用法。五、扩展与合并一对容易混淆的概念在与扩展类型相关的语境中另一个高频概念是合并Merging。仓库 Merging and Extension 明确区分了两者合并把同名的多次声明合并为一个定义。例如重复声明同一个interface XTypeScript 会把它们的成员合并interface X { a: string; } interface X { b: number; } const person: X { a: a, b: 7, };扩展从既有类型派生出新类型不改动原类型。上文的interface Bird extends Animal即属此类。二者的关键区别合并不产生新名字只是扩充同名声明扩展产生新类型名原类型保持不变。在 Differences between Type and Interface 中声明合并Declaration Merging被明确列为接口专有能力——type不支持声明合并这也是需要为扩展后的结果留出后续扩展空间时优先选择interface的重要原因。六、实战选型什么时候用 extends什么时候用 综合原书第 16 节与仓库相邻章节可以整理出如下决策依据场景推荐写法理由基于已有接口派生新接口且新接口仍可被继承/合并interface Y extends X { ... }保持接口的开放性与可合并能力需要一次性继承多个契约interface Y extends A, B { ... }接口支持多继承类不支持基础形状是type对象字面量、别名、联合等type C A Bextends对type不可用是标准扩展手段需要组合联合类型、字面量类型等复杂形状type T U V可以组合任意类型表达式以type为基础希望结果参与接口继承链interface B extends A {}A 为 type允许接口继承 type方向合法想在不改原定义的前提下扩充同名接口重复声明同名interface触发声明合并仅接口可用无论选择哪条路径最终对象都必须同时满足所有被扩展类型的全部成员约束这是结构类型系统的底层要求也是 Intersection Types 中示例反复验证的结论type A { foo: number }; type B { bar: string }; type C A B; const obj: C { foo: 42, bar: hello }; // 缺少任一字段即报错七、扩展类型时的边界与注意事项同名成员冲突多接口继承或交叉组合时若两个来源定义了同名但类型不兼容的成员接口继承会报错交叉类型会把该成员推导为不兼容类型实践中通常等于never。设计复合契约时应避免来源间的同名冲突。联合类型无法被接口继承接口只能扩展对象形状的声明不能extends一个联合类型如string | number。需要处理联合时请回到type/|的组合路线参见 Differences between Type and Interface 的 Union and Intersection Types。扩展不改变原始类型无论extends还是都是派生新类型而非原地修改。这与合并修改同名声明形成对照也保证了既有代码不受影响Merging and Extension。接口合并的能力边界声明合并虽强大但type无法享受这一能力。若你预判某个契约将来会被第三方代码或业务模块补丁式扩展优先用interface建模。八、延伸阅读Extending Types波兰语版本主题原文Intersection Types运算符的完整定义与示例Merging and Extension合并与扩展的语义区分Differences between Type and Interfacetype 与 interface 的全方位对比Interface and Type两种声明的常见语法Type Manipulation从既有类型派生新类型的更多手段映射类型、条件类型、工具类型Classextends在类继承与多接口实现中的应用Erased Structural Types结构类型系统如何支撑扩展语法赞分享文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载相关推荐TypeScript 类型扩展全指南interface extends、多重继承与交集类型实战The Concise TypeScript Book 精读TypeScript 类型扩展全指南interface extends、多重继承与交集类型实战The Concise TypeScript Book 精读文档教程TypeScript 类型扩展完全指南interface extends、多重继承与交叉类型实战typescript-bookTypeScript 类型扩展完全指南interface extends、多重继承与交叉类型实战typescript book 本指南以《The Conc文档教程深入理解 TypeScript 类型扩展interface extends、类型交集与 The Concise TypeScript Book 中的实战法则深入理解 TypeScript 类型扩展interface extends、类型交集与 The Concise TypeScript Book 中的实战法则文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?