让你更好使用 Typescript 的11个技巧

学习Typescript通常是一个重新发现的过程。最初印象可能很有欺骗性:这不就是一种注释Javascript 的方式吗,这样编译器就能帮助我找到潜在的bug?,虽然这种说法总体上是正确的,但随着你的前进,会发现语言最不可思议的力量在于组成、推断和操纵类型。,本文将总结几个技巧,帮助你充分发挥语言的潜力。,类型是程序员日常概念,但很难简明地定义它。我发现用集合作为概念模型很有帮助。,例如,新的学习者发现Typescript组成类型的方式是反直觉的。举一个非常简单的例子:,如果你将 & 操作符解释为逻辑与,你的可能会认为 Circle 是一个哑巴类型,因为它是两个没有任何重叠字段的类型的结合。这不是 TypeScript 的工作方式。相反,将其想象成集合会更容易推导出正确的行为:,集合也有助于理解可分配性:只有当值的类型是目标类型的子集时才允许赋值:,TypeScript 有一项非常强大的功能是基于控制流的自动类型收窄。这意味着在代码位置的任何特定点,变量都具有两种类型:声明类型和类型收窄。,在定义一组多态类型(如 Shape)时,可以很容易地从以下开始:,需要使用非空断言(在访问 radius、width 和 height 字段时),因为 kind 与其他字段之间没有建立关系。相反,区分联合是一个更好的解决方案:,类型收窄已经消除了强制转换的需要。,如果你正确使用 TypeScript,你应该很少会发现自己使用显式类型断言(例如 ​​value as SomeType​​);但是,有时你仍然会有一种冲动,例如:,一个更优雅的解决方案是将isCircle和isRect改为返回类型谓词,这样它们可以帮助Typescript在调用 filter 后进一步缩小类型。,类型推断是Typescript的本能;大多数时候,它公默默地工作。但是,在模糊不清的情况下,我们可能需要干预。分配条件类型就是其中之一。,假设我们有一个ToArray辅助类型,如果输入的类型不是数组,则返回一个数组类型。,你认为对于以下类型,应该如何推断?,答案是string[] | number[]。但这是有歧义的。为什么不是(string | number)[] 呢?,默认情况下,当typescript遇到一个联合类型(这里是string | number)的通用参数(这里是T)时,它会分配到每个组成元素,这就是为什么这里会得到string[] | number[]。这种行为可以通过使用特殊的语法和用一对[]来包装T来改变,比如。,现在,Foo 被推断为类型(string | number)[],在对枚举进行 switch-case 操作时,最好是积极地对不期望的情况进行错误处理,而不是像在其他编程语言中那样默默地忽略它们:,使用Typescript,你可以通过利用never类型,让静态类型检查提前为你找到错误:,有了这个,在添加一个新的shape kind时,就不可能忘记更新getArea函数。,这种技术背后的理由是,never​ 类型除了 never​ 之外不能赋值给任何东西。如果所有的 shape.kind​ 候选者都被 case​ 语句消耗完,到达default 的唯一可能的类型就是 never​;但是,如果有任何候选者没有被覆盖,它就会泄漏到 default 分支,导致无效赋值。,在 TypeScript 中,当用于对对象进行类型定义时,type​ 和 interface​ 构造很相似。尽管可能有争议,但我的建议是在大多数情况下一贯使用 type​,并且仅在下列情况之一为真时使用 interface:,你想利用interface的 “合并”功能。,你有遵循面向对象风格的代码,其中包含类/接口层次结构,否则,总是使用更通用的类型结构会使代码更加一致。,在适当的时候优先选择元组而不是数组,对象类型是输入结构化数据的常见方式,但有时你可能希望有更多的表示方法,并使用简单的数组来代替。例如,我们的Circle可以这样定义:,但是这种类型检查太宽松了,我们很容易通过创建类似 [‘circle’, ‘1.0’] 的东西而犯错。我们可以通过使用 Tuple 来使它更严格:,Tuple使用的一个好例子是React的useState:,它既紧凑又有类型安全。,在进行类型推理时,Typescript使用了合理的默认行为,其目的是使普通情况下的代码编写变得简单(所以类型不需要明确注释)。有几种方法可以调整它的行为。,使用const来缩小到最具体的类型,使用satisfies来检查类型,而不影响推断的类型,考虑以下例子:,我们遇到了错误,因为根据circle​的声明类型NamedCircle​,name​字段确实可能是undefined​,即使变量初始值提供了字符串值。当然,我们可以删除:NamedCircle​类型注释,但我们将为circle对象的有效性丢失类型检查。相当的困境。,幸运的是,Typescript 4.9 引入了一个新的satisfies关键字,允许你在不改变推断类型的情况下检查类型。,修改后的版本享有这两个好处:保证对象字面意义符合NamedCircle类型,并且推断出的类型有一个不可为空的名字字段。,在设计实用功能和类型时,我们经常会感到需要使用从给定类型参数中提取出的类型。在这种情况下,infer关键字非常方便。它可以帮助我们实时推断新的类型参数。这里有两个简单的示例:,T extends Promise<infer U>​中的infer​关键字的工作方式可以理解为:假设T与某些实例化的通用Promise类型兼容,即时创建类型参数U​使其工作。因此,如果T​被实例化为Promise<string>​,则U的解决方案将是string。,Typescript提供了强大的类型操作语法和一套非常有用的工具,帮助你把代码重复率降到最低。,不是重复声明:,而是使用Pick工具来提取新的类型:,不是重复函数的返回类型,而是使用ReturnType<T>来提取它:,不是并行地同步两种类型的形状(这里是typeof config​和Factory)。,而是使用Mapped Type​和Template Literal Type,根据配置的形状自动推断适当的工厂类型。,本文涵盖了Typescript语言中的一组相对高级的主题。在实践中,您可能会发现直接使用它们并不常见;然而,这些技术被专门为Typescript设计的库大量使用:比如Prisma和tRPC。了解这些技巧可以帮助您更好地了解这些工具如何在引擎盖下工作。,原文:https://dev.to/zenstack/11-tips-that-help-you-become-a-better-typescript-programmer-4ca1

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/16843.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34