ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

The Concise TypeScript Book 精读:对象类型(Object Types)的三种定义方式与工程化实战

The Concise TypeScript Book 精读:对象类型(Object 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点击查看免费下载对象类型Object Types是 TypeScript 类型系统的基石它描述“一个对象长什么样”有哪些属性、每个属性的类型是什么、属性是必填还是可选。本文以开源仓库 typescript-book 中《The Concise TypeScript Book》第 28 章 object-types.md捷克语译本英文原版见 website/src/content/docs/book/object-types.md为核心骨架结合同书相邻章节的源码级示例系统讲解 interface、type alias、匿名对象类型三种定义方式以及可选属性、只读属性、索引签名、联合/交叉类型、映射类型等进阶能力。读完本文你将能独立判断何时用 interface、何时用 type并写出结构清晰、可复用的对象类型声明。一、对象类型描述对象的“形状”在 TypeScript 中对象类型object type描述的是一组对象的公共形状shape它规定对象的属性名称、每个属性对应的类型以及这些属性是必填还是可选。通俗地说对象类型就是一份“属性清单”编译器依据这份清单对对象字面量、函数参数、返回值进行静态检查。从 object-types.md 的定义看一个对象类型需要回答三个问题有哪些属性属性名每个属性的类型是什么值类型属性是否必需required / optional。例如下面的声明描述了一个“用户”对象必须有name字符串和age数字email可以有也可以没有interface User { name: string; age: number; email?: string; }email?: string末尾的问号正是“可选属性”的语法标记它回答了上述第三个问题。二、定义对象类型的三种方式TypeScript 提供了三种书写对象类型的方式第 28 章逐一给出了最小示例。2.1 方式一interface接口接口通过指定属性的名称、类型和可选性来定义对象的形状interface User { name: string; age: number; email?: string; }interface的语义是“契约”任何被标注为User的值都必须满足这个形状。接口还可以声明方法成员例如同书 interface-and-type.md 中的示例interface Person { name: string; age: number; greet(): void; }方法成员由方法名、括号内的参数列表和返回类型组成多个成员之间用分号分隔。2.2 方式二type alias类型别名类型别名与接口类似也能描述对象形状但它的能力边界更宽它可以在已有类型或类型组合的基础上创建出全新的自定义类型包括联合类型union、交叉类型intersection以及其他复杂类型type Point { x: number; y: number; };注意type使用进行赋值式声明而interface直接使用声明语句这是两者最直观的语法差异详见 differences-between-type-and-interface.md。2.3 方式三匿名对象类型inline / anonymous对象类型不必起名字可以直接“内联”在需要它的位置。第 28 章的示例将匿名对象类型直接写在函数参数上const sum (x: { a: number; b: number }) x.a x.b; console.log(sum({ a: 5, b: 1 }));(x: { a: number; b: number })中的{ a: number; b: number }就是一个匿名对象类型。它适合“一次性使用”的场景——结构不会被复用就不必为其命名。interface-and-type.md 中也有等价的内联写法const x: { name: string; age: number } { name: Simon, age: 7 };三、深入属性细节可选、只读与索引签名对象类型不止于“列出属性名和类型”它还能精确控制每个属性的行为语义。3.1 可选属性Optional Properties在属性名后追加?即可声明该属性可选。第 13 章 optional-properties.md 给出了完整示例type X { a: number; b?: number; // Optional };可选属性在读取时类型会变为number | undefined因此使用前需要做存在性判断。若属性可选还可以在解构时给出默认值让逻辑更稳健type X { a: number; b?: number; }; const x ({ a, b 100 }: X) a b;当b未传入时自动回退到100避免运行时undefined参与运算。3.2 只读属性readonlyreadonly修饰符可以阻止对属性的后续写入但它只约束“不能重新赋值”并不提供深层次的不可变性保证嵌套对象内部仍可能被修改。第 14 章 readonly-properties.md 给出了四种等价/相近的写法interface Y { readonly a: number; } type X { readonly a: number; }; type J Readonly{ a: number; }; type K { readonly [index: number]: string; };其中Readonly{ a: number }是 TypeScript 内置的映射工具类型它把传入类型的所有属性批量加上readonly最后一种写法把readonly应用在数字索引签名上即“该数组/字典的所有下标只读”。3.3 索引签名Index Signatures当对象的属性键无法提前枚举时例如字典、哈希表可以使用索引签名。第 15 章 index-signatures.md 展示了string | number双键写法type K { [name: string | number]: string; }; const k: K { x: x, 1: b }; console.log(k[x]); console.log(k[1]); console.log(k[1]); // Same result as k[1]这里有一个重要的 JavaScript 运行时事实数字索引会被自动强制转换为字符串。因此k[1]与k[1]访问的是同一个键返回值相同。理解这一点可以避免把number和string键误当成两套独立存储。四、组合对象类型扩展、联合与交叉单一的对象类型往往不够用TypeScript 提供了把多个对象类型组合起来的机制。4.1 用 extends 扩展接口第 16 章 extending-types.md 说明接口可以通过extends复制其他类型的成员且支持多继承interface X { a: string; } interface Y extends X { b: string; } // 多类型继承 interface A { a: string; } interface B { b: string; } interface Y2 extends A, B { y: string; }关键约束是extends关键字只适用于接口interface和类class。类型别名没有extends组合多个 type 时要使用交叉类型type A { a: number; }; type B { b: number; }; type C A B;另外还有一个方向性限制类型别名可以被接口extends接口继承类型别名反过来则不行——类型别名无法extends接口type A { a: string; }; interface B extends A { b: string; }4.2 联合类型与交叉类型联合类型union用|连接表示“值可能是其中任意一种”。第 32 章 union-type.md 的示例let x: string | number; x hello; // Valid x 123; // Valid交叉类型intersection用连接表示“值同时拥有所有类型的全部属性”。第 33 章 intersection-types.md 的示例type X { a: string; }; type Y { b: string; }; type J X Y; // Intersection const j: J { a: a, b: b, };交叉类型在组合多个 DTO、混入mixin等场景中非常常见。4.3 interface 与 type 的选择声明合并第 54 章 differences-between-type-and-interface.md 系统梳理了两者的差异其中最关键的一条是声明合并declaration merging同名 interface 可以被多次声明并自动合并成一个接口而 type 不允许同名重复声明。interface A { x: string; } interface A { y: string; } const j: A { x: xx, y: yy, };这在“不修改第三方类型定义的前提下为其补充成员”时很有价值例如为库暴露的接口扩展字段。但合并行为也可能掩盖命名冲突属于“双刃剑”。两者在组合能力上的差异总结如下能力interfacetype alias描述对象形状✅✅声明合并同名多次声明✅❌用extends扩展✅接口/类❌被其他接口extends—✅接口可继承类型别名定义联合类型A \| B间接可用类型别名包一层✅ 直接定义交叉类型A B无内建支持✅ 直接定义其他复杂类型有限✅ 更灵活典型取舍需要开放扩展如库的公共 API 类型、可被消费者合并时倾向interface需要联合、交叉、条件、映射等复杂类型运算时倾向type。五、进阶映射类型与结构化类型的运行真相5.1 映射类型批量改造对象类型第 38 章 mapped-types.md 展示了如何借助keyof遍历已有类型的每个属性并套用映射函数生成新类型。下面的MyMappedTypeT把每个属性都变成“该类型元素的数组”type MyMappedTypeT { [P in keyof T]: T[P][]; }; type MyType { foo: string; bar: number; }; type MyNewType MyMappedTypeMyType; const x: MyNewType { foo: [hello, world], bar: [1, 2, 3], };MyNewType与MyType表达的信息一一对应只是每个字段的形态从“单个值”变成了“值的数组”。这种“同一信息、不同格式”的类型变换能力是 TypeScript 类型编程的核心手段之一前面提到的内置ReadonlyT也是同类机制的产物。5.2 结构化类型structural typing与多余属性对象类型的匹配是结构化的只要形状满足要求即可不需要显式的继承或实现关系。第 57 章 erased-structural-types.md 演示了这一点type NameProp1 { prop1: string; }; function log(x: NameProp1) { console.log(x.prop1); } const obj { prop2: 123, prop1: Origin, }; log(obj); // Validobj多出prop2属性但它仍然满足NameProp1的形状要求因此可以传给log。不过需要注意对象字面量fresh object literal在直接赋值时会触发“多余属性检查”excess property checking编译器会对字面上多出来的属性报错上例通过中间变量obj传递则绕开了这一限制。这是结构化类型与字面量新鲜度检查之间的一个经典差异。5.3 strictNullChecks 对对象属性的影响默认情况下null/undefined可以赋值给任何类型这常常是运行时崩溃的根源。开启strictNullChecks后第 19 章 strictnullchecks.md 指出只有显式声明为T | null | undefined的变量和参数才能接收空值否则编译器直接报错。这对对象类型的设计有直接影响——例如“可选属性在读取时是T | undefined”配合严格空值检查可以强制开发者在访问前做判空从而把潜在的空指针问题消灭在编译期。本仓库的网站工程在 website/tsconfig.json 中继承了astro/tsconfigs/strict即默认开启严格模式可作为实际项目配置的参照。六、最佳实践小结结合 object-types.md 及同书相关章节可以沉淀出如下几条可落地的建议优先用对象字面量内联类型还是命名类型结构只出现一次用匿名对象类型如函数参数直接写{ a: number; b: number }结构会被多处复用立即提取为interface或type。可选属性一律加?并配合默认值或判空逻辑不要用“可能缺失但没标注”的属性否则在strictNullChecks下会立刻收到编译错误。需要对外扩展第三方补丁、插件机制用interface利用声明合并能力需要联合、交叉、映射等复杂运算用type避免用 interface 表达不了的结构。组合多个对象类型接口之间用extends类型别名之间用交叉类型跨类别组合时记住“type 可以被 interface extends反之不行”。为属性语义把关不变的数据用readonly键不固定用索引签名并牢记“数字索引会被转成字符串索引”这一运行时事实。以上所有示例均可在仓库的 website/src/content/docs/cs-cz/book/捷克语译本与 website/src/content/docs/book/英文原版对应章节中直接找到原文与完整上下文适合作为进一步学习的索引起点。赞分享文档教程【免费下载链接】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点击查看免费下载相关推荐The Concise TypeScript Book 实战深入理解 TypeScript 对象类型Object Types的三种定义方式与底层原理The Concise TypeScript Book 实战深入理解 TypeScript 对象类型Object Types的三种定义方式与底层原理 对象文档教程The Concise TypeScript Book 精讲对象类型Object Types从定义到组合实战The Concise TypeScript Book 精讲对象类型Object Types从定义到组合实战 导读 对象类型是 TypeScript 类型文档教程The Concise TypeScript Book 精讲扩展类型Extending Types的三种方式、适用边界与实战要点The Concise TypeScript Book 精讲扩展类型Extending Types的三种方式、适用边界与实战要点 本篇技术指南围绕 The文档教程上一篇StoryDiffusion完整使用指南从零开始创作AI漫画故事下一篇The Mirror多人协作开发从版本冲突到实时同步的进化之路创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表