您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

TypeScript 4.9 发布!重点新特性解读

时间:2022-11-07 17:01:11  来源:今日头条  作者:Echa攻城狮


 

大家好,我是 Echa。

11 月 1 日,TypeScript 4.9 发布了候选版本 (RC),直到稳定版发布基本上不会有太大变化了,本次带来的更新还是挺有意思的,下面我就跟大家来一起看一下~

新的 satisfies 操作符

在使用 TypeScript 类型推断的时候,有很多情况下会让我们面临两难的选择:我们即希望确保某些表达式能够匹配某些类型,但也希望保留这个表达式的特定类型用来类型推断。

比如下面的例子,我们定义了一个颜色选择对象:

const palette = { red: [255, 0, 0], green: "#00ff00", blue: [0, 0, 255] };

因为每个属性都被赋予了默认值,ts 会自动帮我们自动推导 palette 的属性类型,所以我们可以直接调用它们的方法:

// red 被推断为 Number[] 类型 const a = palette.red.at(0); // green 被推断为 string 类型 const b = palette.green.toUpperCase();

因为颜色都是固定的,我们想让我们的 palette 对象拥有特定的几个属性,来避免我们写出一些错别字:

const palette = { // 错别字:rad -> red rad: [255, 0, 0], green: "#00ff00", blue: [0, 0, 255] };

所以我们可能会为 palette 定义一个类型,这样错别字就会被检测出来了:

type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette: Record = { rad: [255, 0, 0], // ~~~~ The typo is now correctly detected green: "#00ff00", blue: [0, 0, 255] };

但是这时候我们再调用 palette.red 的方法,你会发现 TS 的类型推断会出错:

type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette: Record = { red: [255, 0, 0], green: "#00ff00", blue: [0, 0, 255] }; // 'palette.red' "could" 的类型是 string | RGB ,所以它不一定存在 at 方法 const a = palette.red.at(0);

这就让我们陷入了两难的境地,我们用更严格了类型约束了写出 bug 的可能性,但是却失去了类型推断的能力。

satisfies 关键字就是用来解决这个问题的,它既能让我们验证表达式的类型是否与某个类型匹配,也可以保留基于值进行类型推断的能力:

type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette = { rad: [255, 0, 0], // 可以捕获到错别字 rad green: "#00ff00", blue: [0, 0, 255] } satisfies Record; // 都可以调用 const a = palette.red.at(0); const b = palette.green.toUpperCase(); in 操作符类型收窄优化

在日常开发中,我们经常需要处理一些在运行时不完全确定的值,比如我们现在有下面两个类型:

interface Duck { quack(): string; } interface Cat { miao(): string; }

在实际使用过程中,TS 不能确定 value 是否是上面中哪一个类型,所以会抛出错误:

function main(value: Duck | Cat) { if (value.quack) { // roperty 'quack' does not exist on type 'Duck | Cat'. return value.quack; } }

我们可能会使用 in 这样的关键字来实现简单的类型收窄:

function main(value: Duck | Cat) { if ('quack' in value) { return value.quack; } }

也可以实现一个更通用的类型守卫,可以参考我这篇文章:什么是鸭子类型?

 

但是,这个写法的前提是我们用到的对象有明确的类型,如果这个对象的属性没有明确的类型呢?我们来看看下面这段 JAVAScript 代码:

function tryGetPackageName(context) { const packageJSON = context.packageJSON; // 检查是否是个对象 if (packageJSON && typeof packageJSON === "object") { // 检查是否存在一个字符串类型的 name 属性 if ("name" in packageJSON && typeof packageJSON.name === "string") { return packageJSON.name; } } return undefined; }

把这段代码重写为规范的 TypeScript,我们只需要定义一个 Context 类型,但是由于 packageJSON 没有明确的类型定义,再使用 in 进行类型收窄就有问题了:

interface Context { packageJSON: unknown; } function tryGetPackageName(context: Context) { const packageJSON = context.packageJSON; // 检查是否是个对象 if (packageJSON && typeof packageJSON === "object") { // 检查是否存在一个字符串类型的 name 属性 if ("name" in packageJSON && typeof packageJSON.name === "string") { // ~~~~ // error! Property 'name' does not exist on type 'object. return packageJSON.name; // ~~~~ // error! Property 'name' does not exist on type 'object. } } return undefined; }

这是因为 in 操作符只会严格收窄到实际定义被检查属性的类型,所以 packageJSON 的类型从 unknown 收窄到了 object ,而 object 类型上不存在 name 属性,就会引发报错。

TypeScript 4.9 优化了这个问题,in 操作符更加强大了,它会被收窄为被检查类型和 Record<"property-key-being-checked", unknown> 的交叉类型。。。

比如在上面的例子中,packageJSON 的类型会被收窄为 object & Record<"name",unknown>,这样我们直接访问 packageJSON.name 就没问题了!

interface Context { packageJSON: unknown; } function tryGetPackageName(context: Context): string | undefined { const packageJSON = context.packageJSON; // 检查是否是个对象 if (packageJSON && typeof packageJSON === "object") { // 检查是否存在一个字符串类型的 name 属性 if ("name" in packageJSON && typeof packageJSON.name === "string") { // 可以正常运行! return packageJSON.name; } } return undefined; }

TypeScript 4.9 还加强了一些关于如何使用 in 操作符的检查,比如左侧要检查的属性必须是 string | number | symbol 类型,而右侧类型必须要可分配给 object。
accessor 关键字支持

 

accessor 是 ECMAScript 中即将推出的一个类关键字,TypeScript 4.9 对它提供了支持:

class Person { accessor name: string; constructor(name: string) { this.name = name; } }

accessor 关键字可以为该属性在运行时转换为一对 get 和 set 访问私有支持字段的访问器:

class Person { #__name: string; get name() { return this.#__name; } set name(value: string) { this.#__name = name; } constructor(name: string) { this.name = name; } } NaN 相等判断警告

NaN 是一个特殊的数值,代表 “非数字” ,在 JS 中它和任何值相比较都是 false,包括它自己:

console.log(NaN == 0) // false console.log(NaN === 0) // false console.log(NaN == NaN) // false console.log(NaN === NaN) // false

相对应的,所有值都不等于 NaN

console.log(NaN != 0) // true console.log(NaN !== 0) // true console.log(NaN != NaN) // true console.log(NaN !== NaN) // true

这其实并不是 JavaScript 特有的问题,因为任何包含 IEEE-754 浮点数的语言都有相同的行为;但 JavaScript 的主要数字类型就是浮点数,并且 JavaScript 中的数字解析为 NaN 还挺常见的,所以在代码中去比较值是否等于 NaN 的情况还挺普遍的。但是正确的做法应该是使用 Number.isNaN 函数来判断。假如你不知道这个问题,就可能引发一些 bug。

在 TypeScript 4.9 中,如果你直接用一些值和 NaN 相比较,会抛出错误并提示你使用 Number.isNaN

function validate(someValue: number) { return someValue !== NaN; // ~~~~~~~~~~~~~~~~~ // error: This condition will always return 'true'. // Did you mean '!Number.isNaN(someValue)'? } return 关键字的定义

在编辑器中,当你对 return 关键字运行 go-to-definition 时,TypeScript 现在会自动跳转到相应函数的顶部。这有助于我们快速了解 return 属于哪个函数。

另外,TypeScript 会将此功能扩展到更多关键字,例如 await、yield、switch、case、default 等等。

最后

TypeScript 团队最近还发布了 5.0 版本的迭代规划(https://Github.com/microsoft/TypeScript/issues/51362),这将是 TypeScript 的又一个大的版本,其中包含了很多有趣的想法,还是挺值得期待的!

更多详细更新请查看 TypeScript 官方博客:https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-rc/

你觉得上面哪些更新对你最有用呢?欢迎在评论区和我留言;如果这篇文章帮助到了你,欢迎点赞和关注。



Tags:TypeScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
一篇文章搞懂TypeScript
TypeScript 是 JavaScript 的超集,一方面给动态类型的 js 增加了类型校验,另一方面扩展了 js 的各种功能。原始数据类型 字符串 数值 布尔 null undefined Symbol BigIntlet s...【详细内容】
2024-01-08  Search: TypeScript  点击:(80)  评论:(0)  加入收藏
TypeScript中的null和undefined的区别
在TypeScript中,null和undefined是两个特殊的值,用于表示变量的缺失或未定义。尽管它们在某些情况下可能看起来相似,并且都可以表示"没有值",但它们在语义和用法上存在一些重要...【详细内容】
2023-12-07  Search: TypeScript  点击:(136)  评论:(0)  加入收藏
为什么要在项目中使用TypeScript?
译者 | 李睿随着越来越多的开发人员采用TypeScript,人们需要了解在下一个项目中应该使用TypeScript的原因。尽管它在早期应用中遇到了一些阻力,但在过去十年,它迅速成为一种广...【详细内容】
2023-11-30  Search: TypeScript  点击:(166)  评论:(0)  加入收藏
一文读懂 TypeScript 泛型及应用
泛型是静态类型语言的基本特征,允许将类型作为参数传递给另一个类型、函数、或者其他结构。TypeScript 支持泛型作为将类型安全引入组件的一种方式。这些组件接受参数和返回...【详细内容】
2023-11-20  Search: TypeScript  点击:(196)  评论:(0)  加入收藏
TypeScript 5.3 来了,一大波新特性
根据 TypeScript 路线图,TypeScript 5.3 计划于 11 月 14 日发布。下面是该版本带来的新特性: 导入属性 导入类型中稳定支持 resolution-mode 所有模块模式均支持 resolution-...【详细内容】
2023-11-16  Search: TypeScript  点击:(163)  评论:(0)  加入收藏
万字详解 TypeScript 高级用法
TypeScript 是一种类型安全的 JavaScript 超集,除了基本类型和对象类型之外,TypeScript 还提供了一些高级类型系统,使得我们可以更好地处理复杂的数据结构和业务逻辑。本文将深...【详细内容】
2023-10-31  Search: TypeScript  点击:(340)  评论:(0)  加入收藏
不要在Typescript中使用Function类型
原文链接:https://www.totaltypescript.com/dont-use-function-keyword-in-typescript翻译:一川在Typescript中不应该使用Function作为一个类型,因为它可以表示任何函数。通常,...【详细内容】
2023-09-27  Search: TypeScript  点击:(279)  评论:(0)  加入收藏
为什么选择 TypeScript,它有什么优点吗?
在当今快速发展的软件开发领域,TypeScript技术的重要性日益凸显。TypeScript是一种由微软开发的开源编程语言,它扩展了JavaScript,并为开发者提供了强大的静态类型检查。首先,Ty...【详细内容】
2023-09-22  Search: TypeScript  点击:(192)  评论:(0)  加入收藏
掌握TypeScript,开启高质量前端之旅
相信TypeScript对于一个前端开发来讲应该是不陌生的,因为作为一个前端开发者来说,不是在学习如何使用TS就是在去学习TS如何使用的路上。为什么这么说呢?一些技术的发展离不开人...【详细内容】
2023-09-22  Search: TypeScript  点击:(283)  评论:(0)  加入收藏
反驳来了!放弃TypeScript?说明你无知!
作者 | Robert Vitonsky编译 | 云中 几天前,汉森 (David Heinemeier Hansson)宣布 Turbo8 即将放弃 TypeScript。我心想:放弃就放弃吧,反正我也不知道 Turbo 8 是什么鬼。 然而...【详细内容】
2023-09-15  Search: TypeScript  点击:(232)  评论:(0)  加入收藏
▌简易百科推荐
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(2)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(7)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(13)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(9)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(11)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(9)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
站内最新
站内热门
站内头条