ARTICLE DETAIL

资讯详情

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

The Concise TypeScript Book:深入解析 TypeScript 类型收窄(Narrowing)五大核心手段

The Concise TypeScript Book:深入解析 TypeScript 类型收窄(Narrowing)五大核心手段 文档教程【免费下载链接】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》英文原版的 西班牙语版 Restricción 章节 为核心骨架系统讲解 TypeScript 中类型收窄Narrowing的完整技术体系。读完本文你将掌握typeof、真值判断、相等性、in运算符、instanceof五种收窄手段的适用场景与代码写法并能结合控制流分析、判别联合Discriminated Unions、类型谓词Type Predicates等进阶机制在实际项目中写出类型安全的代码。什么是类型收窄类型收窄Narrowing是 TypeScript 编译器在条件代码块内将变量的类型从宽泛类型精确为更具体类型的过程。当变量属于联合类型Union Type、可能同时拥有多种类型时收窄机制尤为关键。先看联合类型的基本形态参见 Union Type 章节let x: string | number; x hello; // Valid x 123; // Valid在没有收窄之前x的类型始终是string | number调用任何仅属于单一类型的方法都会报错。类型收窄的价值正是让 TypeScript 在特定代码路径上「知道」x此刻到底是string还是number从而安全调用对应类型的方法与属性。原文档明确指出TypeScript 会识别多种收窄方式。下面逐一展开。typeof 类型守卫typeof类型守卫是 TypeScript 特有的一种守卫Type Guard它基于 JavaScript 的内建类型来检查变量的类型。由于typeof是 JavaScript 原生运算符这一手段零运行时开销、任何环境通用是最基础也最常用的收窄方式。原文档示例const fn (x: number | string) { if (typeof x number) { return x 1; // x is number } return -1; };在这个例子中函数参数x的声明类型是number | string。当typeof x number为真时TypeScript 将x收窄为number因此x 1的算术运算合法而进入if之后剩余的代码路径上x被收窄为string返回-1也不需要访问字符串成员因此不会报错。实战要点typeof可识别的 JavaScript 内建类型包括string、number、boolean、bigint、symbol、undefined、function、object。typeof null的返回值是object因此无法用typeof区分null与对象此时应改用下面的真值收窄或显式的 null判断。typeof对数组返回object判断数组应使用Array.isArray()这一点在 exploring-the-type-system.md 的「Restricción de tipos」小节中被列为内建收窄函数。真值收窄Truthiness Narrowing真值收窄通过判断变量在布尔上下文中是真值truthy还是假值falsy从而收窄其类型。它特别适用于处理可能为null、undefined或空字符串的联合类型。原文档示例const toUpperCase (name: string | null) { if (name) { return name.toUpperCase(); } else { return null; } };当name为非空字符串时if (name)为真TypeScript 将name收窄为string可以安全调用name.toUpperCase()否则返回null。实战要点JavaScript 中的假值包括false、0、-0、0n、、null、undefined、NaN。也就是说真值收窄不仅排除null/undefined还会把空字符串、数字0等一并排除。因此当业务上需要「空字符串也属于合法值」时不要用真值收窄应改为显式判断name ! null name ! undefined。真值收窄可以连续叠加使用例如if (name name.length 0)编译器会在右侧继续把name视为string。相等性收窄Equality Narrowing相等性收窄通过检查变量是否等于或不等某个具体值来收窄其类型。它常与switch语句以及、!、、!等相等性运算符配合使用。原文档示例const checkStatus (status: success | error) { switch (status) { case success: return true; case error: return null; } };在这里status是字面量联合类型success | error。switch的每个case分支都是一个收窄点进入case success时status被收窄为success进入case error时被收窄为error。实战要点相等性收窄同样适用于 null、! undefined这类显式判断是处理可选值可选属性、可空参数最常见的收窄写法。在 exploring-the-type-system.md 的「Restricción de tipos」小节中有对应演示x: number | undefined经过if (x ! undefined)之后块内x被收窄为number可以执行x 100。另一个被原书收录的「提前返回」模式在函数开头if (x undefined) { throw error; }之后后续代码中x恒为number无需再嵌套条件块。若switch分支未覆盖全部联合成员结合never类型可做穷尽性检查详见 Comprobación exhaustiva 章节在default分支中声明const exhaustiveCheck: never direction;一旦联合类型新增成员而switch未处理编译器即报错。in 运算符收窄in运算符收窄根据对象类型中是否存在某个属性来决定收窄方向。它特别适用于结构不同但类型相互重叠的联合类型——各成员没有共享的可判别字面量属性但可以通过各自独有的属性来区分。原文档示例type Dog { name: string; breed: string; }; type Cat { name: string; likesCream: boolean; }; const getAnimalType (pet: Dog | Cat) { if (breed in pet) { return dog; } else { return cat; } };Dog与Cat共享name属性但只有Dog有breed、只有Cat有likesCream。breed in pet为真时pet被收窄为Dog否则为Cat。实战要点in运算符的右侧必须是对象类型或对象类型的联合左侧为字符串字面量或可推断为字符串的表达式。若联合成员共享属性过多、无法靠单一属性区分应优先考虑**判别联合Discriminated Union**模式为每个成员加上唯一的字面量判别属性如kind再配合switch收窄。完整示例与运行结果见 Uniones discriminadas 章节type Square { kind: square; // Discriminant size: number; }; type Circle { kind: circle; // Discriminant radius: number; }; type Shape Square | Circle; const area (shape: Shape) { switch (shape.kind) { case square: return Math.pow(shape.size, 2); case circle: return Math.PI * Math.pow(shape.radius, 2); } }; const square: Square { kind: square, size: 5 }; const circle: Circle { kind: circle, radius: 2 }; console.log(area(square)); // 25 console.log(area(circle)); // 12.566370614359172instanceof 收窄instanceof收窄根据变量的构造函数来收窄类型通过检查一个对象是否为某个类或接口的实例实现。它是处理「同一联合中多个类类型」时的标准手段。原文档示例class Square { constructor(public width: number) {} } class Rectangle { constructor( public width: number, public height: number ) {} } function area(shape: Square | Rectangle) { if (shape instanceof Square) { return shape.width * shape.width; } else { return shape.width * shape.height; } } const square new Square(5); const rectangle new Rectangle(5, 10); console.log(area(square)); // 25 console.log(area(rectangle)); // 50shape instanceof Square为真时shape被收窄为Square可访问width计算正方形面积否则被收窄为Rectangle使用width * height计算矩形面积。运行结果分别为 25 与 50。实战要点instanceof右侧必须是一个构造函数class 或构造函数它检查的是运行时原型链因此对null、undefined或纯对象字面量类型的联合无效。由于instanceof基于类的继承关系它也适用于父类/子类混合的联合子类实例通过instanceof 父类也会得到收窄结果。若联合成员是纯type/interface无运行时构造函数instanceof无法使用应改用in运算符或判别联合。进阶收窄背后的控制流分析收窄并不是简单的「if 块内生效」而是由 TypeScript 的**控制流分析Control Flow Analysis**机制驱动的。原书在 Análisis del flujo de control 章节 中专门说明了两点关键事实TypeScript 4.4 之前控制流分析仅作用于if语句内部从 TypeScript 4.4 起分析扩展到了条件表达式以及通过const变量间接引用的判别属性访问const f1 (x: unknown) { const isString typeof x string; if (isString) { x.length; // OKisString 是 const收窄生效 } }; const f2 ( obj: { kind: foo; foo: string } | { kind: bar; bar: number } ) { const isFoo obj.kind foo; if (isFoo) { obj.foo; // OK } else { obj.bar; // OK } };收窄失效的边界如果中间变量不是const例如let isString ...之后被修改或者判别对象在函数体内被重新赋值收窄将不生效const f1 (x: unknown) { let isString typeof x string; if (isString) { x.length; // ErrorisString 不是 const无法收窄 } }; const f6 ( obj: { kind: foo; foo: string } | { kind: bar; bar: number } ) { const isFoo obj.kind foo; obj obj; // 函数体内对 obj 赋值 if (isFoo) { obj.foo; // Errorobj 在函数体内被重新赋值收窄失效 } };原文档还特别注明条件表达式中最多分析五层间接引用。这意味着类似const a b; const c a;的多层别名传递TypeScript 会追踪到五层为止。进阶自定义类型守卫与类型谓词当内置收窄手段不足以表达复杂判断时可以编写返回布尔值的函数并用**类型谓词Type Predicates**标注其收窄效果即返回类型写作value is T。原书 Predicados de tipo 章节 给出了完整范例const isString (value: unknown): value is string typeof value string; const foo (bar: unknown) { if (isString(bar)) { console.log(bar.toUpperCase()); } else { console.log(not a string); } };调用isString(bar)之后bar在真分支被收窄为string可安全调用toUpperCase()。在 exploring-the-type-system.md 的「Guardas de tipo definidas por el usuario」小节中还有数组场景的对比——没有谓词守卫时data.filter(x x ! null)的返回类型仍是(string | null)[]而使用自定义守卫(item: string | null): item is string item ! null过滤后返回类型精确为string[]。TypeScript 5.5 起编译器能在.filter等函数中自动推断类型谓词如x is T自动识别undefined/null被移除的情况从而给出更精确的类型并减少报错const nums [1, null, 2].filter(x x ! null); // nums 的类型被推断为 number[]需要说明该自动推断只适用于清晰明确的检查如x ! undefined不适用于模糊的检查如!!x。此外TypeScript 5.3 还引入了switch-true 收窄见 exploring-the-type-system.md 的「Restricción mediante switch-true」小节用switch (true)串联多个布尔条件替代冗长的 if/else 链且每个case内依旧能正确收窄类型类似于简化版的模式匹配function classify(x: unknown) { switch (true) { case typeof x string: return ${x.toUpperCase()}; case typeof x number: return x 0 ? positive : negative; case Array.isArray(x): return [${x.length} items]; default: return something else; } }收窄手段选型速查收窄手段适用场景运行时依赖局限性typeof守卫基础类型string/number/boolean 等联合typeof运算符无法区分null与对象、无法识别数组真值收窄string \| null等可空联合布尔判断会排除0、等合法假值相等性收窄字面量联合、可空值、switch场景相等性运算符需要已知的具体值in运算符收窄结构不同但属性重叠的对象联合in运算符右侧需为对象类型instanceof收窄类实例联合构造函数与原型链对纯类型/接口无效类型谓词守卫复杂判断、数组过滤用户自定义函数需手动编写value is T判别联合 switch多个对象类型共享判别属性无纯类型层面需为每个成员添加唯一判别字段如何在本仓库中验证与深入学习本文所讲解的内容均出自开源项目《The Concise TypeScript Book》该仓库以纯 Markdown 形式组织全书内容适合通读与引用本文主骨架西班牙语版 narrowing.md与 英文原版 一一对应前置知识联合类型见 union-type.md收窄机制底层原理控制流分析见 control-flow-analysis.md进阶收窄手段类型谓词见 type-predicates.md、判别联合见 discriminated-unions.md、穷尽性检查见 exhaustiveness-checking.md系统梳理与更多收窄方式提前返回、Array.isArray、switch-true 等见 exploring-the-type-system.md 的「Restricción de tipos」小节全书目录西班牙语版 table-of-contents.md。需要说明的是本仓库定位为入门到进阶的简明参考书The Concise TypeScript Book各章节以短小精悍的示例为主未内置可独立运行的测试工程仓库中的构建与校验脚本如 tools/verify_codeblocks.py主要用于保障 Markdown 代码块格式正确与类型语义本身无关。建议读者在阅读各章节后将示例代码复制到自己的项目中开启strict模式含strictNullChecks运行tsc实际观察收窄对类型推断的影响——尤其是将const改为let、或在函数体内重新赋值体验控制流分析失效时的报错这比任何文字描述都更直观。赞分享文档教程【免费下载链接】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 类型收窄Narrowing五大手段与进阶用法The Concise TypeScript Book 实战精读TypeScript 类型收窄Narrowing五大手段与进阶用法 类型收窄Narrow文档教程Two-Factor插件社区贡献指南如何参与开源项目开发Two Factor插件社区贡献指南如何参与开源项目开发 欢迎来到WordPress Two Factor插件社区贡献指南 如果你对增强WordPres文档教程GoFr CLI gofr store 实战指南用 YAML 生成类型安全的数据访问层GoFr CLI gofr store 实战指南用 YAML 生成类型安全的数据访问层 gofr store 是 GoFr 官方命令行工具 gofr cli文档教程上一篇【亲测免费】 推荐开源项目FuzzySharp - 强大的模糊字符串匹配库下一篇标题【推荐】Ingress Monitor Controller自动监控Kubernetes与OpenShift应用的智能工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表