澄清TypeScript中的 `satisfies` 操作符

news2024/11/18 13:36:09

图片

TypeScript 的 satisfies 运算符已经推出一段时间了,但它似乎仍然是一个可以用来澄清的混乱来源。

可以把 satisfies 看作是将类型赋给值的另一种方式。

在我们深入研究之前,让我们回顾一下如何赋值类型。

首先,有一个不起眼的“冒号注解”(我们使用这个听起来有点像医学术语的名字,因为这个概念在 TS 文档中并没有真正给出一个名字)。

:表示“这个变量总是这个类型”:

 
const obj: Record<string, string> = {};obj.id = "123";

当你使用冒号注解时,你声明了变量是该类型。

这意味着你赋值给变量的东西必须是该类型:

 
// Type 'number' is not assignable to type 'string'.const str: string = 123;

给变量赋予的类型可能比你最初赋予的类型更宽。

 
let id: string | number = "123";if (typeof numericId !== "undefined") {  id = numericId;}

当你想要有一个默认值,而这个默认值以后可能会被重新赋值时,这个方法非常有用。

但是冒号注释有一个缺点。

当使用冒号时,类型优先于值。

换句话说,如果你声明的类型比你想要的宽,你就被这个宽的类型困住了。

例如,在下面的代码片段中,你没有在routes对象上获得 autocomplete:

 
const routes: Record<string, {}> = {  "/": {},  "/users": {},  "/admin/users": {},};// No error!routes.awdkjanwdkjn;

这就是  satisfies 被设计用来解决的问题。

这意味着它能推断出最窄的可能类型,而不是你指定的更宽的类型:

 
const routes = {  "/": {},  "/users": {},  "/admin/users": {},} satisfies Record<string, {}>;// Property 'awdkjanwdkjn' does not exist on type// '{ "/": {}; "/users": {}; "/admin/users": {}; }'routes.awdkjanwdkjn;

satisfies  还能防止在配置对象中指定错误的内容。

因此,satisfies  和 冒号注解 同样安全。

 
const routes = {  // Type 'null' is not assignable to type '{}'  "/": null,} satisfies Record<string, {}>;

另一种为变量赋值的方式是使用 “ as ” 注解。

与  satisfies  和冒号注解不同,使用 “ as ” 注解可以让你对 TypeScript 说谎。

在这个例子中,你在IDE中看不到错误,但它会在运行时崩溃:

 
type User = {  id: string;  name: {    first: string;    last: string;  };};const user = {} as User;// No error! But this will break at runtimeuser.name.first;

这些谎言有一些限制——你可以给对象添加属性,但是你不能在基本类型之间转换。

例如,你不能强制 TypeScript 将字符串转换为数字......

除非你用那个怪异的“as-as”:

 
// Conversion of type 'string' to type 'number'// may be a mistake because neither type// sufficiently overlaps with the other.const str = "my-string" as number;const str2 = "my-string" as unknown as number;

下面是  as  的合法用法,它用于将对象转换为尚未构造的已知类型:

 
type User = {  id: string;  name: string;};// The user hasn't been constructed yet, so we need// to use 'as' hereconst userToBeBuilt = {} as User;(["name", "id"] as const).forEach((key) => {  // Assigning to a dynamic key!  userToBeBuilt[key] = "default";});

警告:如果你使用  as  作为注解变量的默认方式,那几乎肯定是错误的!

下面的代码看起来很安全,但是一旦你给 User 类型添加了另一个属性, defaultUser 就过时了,而且它不会显示错误!

 
type User = {  id: string;  name: string;};const defaultUser = {  id: "123",  name: "Matt",} as User;

还有一种方法可以给变量赋类型:

什么都不加。

这不是打字错误!

TypeScript 在推断变量类型方面做得很好。

事实上,大多数情况下,你根本不需要输入变量:

 
const routes = {  "/": {},  "/users": {},  "/admin/users": {},};// OK!routes["/"];// Property 'awdahwdbjhbawd' does not exist on type// { "/": {}; "/users": {}; "/admin/users": {}; }routes["awdahwdbjhbawd"];

总结一下,我们有四种方法来给变量赋类型:

  • 冒号注解

  • satisfies

  • as 注解

  • 不注解,让TS推断


由于有不同的方法来做类似的事情,它可能会让人们对何时使用何种方法感到有点困惑。

简单的用例是  satisfies  最适用的:

 
type User = {  id: string;  name: string;};const defaultUser = {  id: "123",  name: "Matt",} satisfies User;

但是大多数时候,当你想给变量赋一个类型时,你可能希望这个类型更宽。

如果这个例子使用的是 satisfies ,那么就不能把 numericId 赋给 id :

 
// colon annotationlet id: string | number = "123";if (typeof numericId !== "undefined") {  id = numericId;}// satisfieslet id = "123" satisfies string | number;if (typeof numericId !== "undefined") {  // Type 'number' is not assignable to type 'string'.  id = numericId;}

经验法则是,你应该只在以下两种特定情况下使用satisfies:

  • 你想要的是变量的精确类型,而不是宽泛类型。

  • 这个类型足够复杂,你需要确保你没有把它搞砸。

欢迎关注公众号:文本魔术,了解更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1428626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用python实现pdf按页切割,以及将pdf转成图片

我们经常遇到需要切割pdf的时候&#xff0c;但是常规手段很难做到 我们可以利用python脚本来实现 需要安装几个库 tk PyPDF2 PyMuPDF pyinstaller 上图&#xff01; 查看结果 切割pdf转存成图像 那我们来详细说一下使用方法 1.输入PDF位置:这里没什么好说的&#xff0c…

基于SpringBoot开发的校刊投稿系统[附源码]

基于SpringBoot开发的校刊投稿系统[附源码] &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 &#x1f…

【Springcloud篇】学习笔记十(十七章):Sentinel实现熔断与限流——Hystrix升级

第十七章_Sentinel实现熔断与限流 1.Sentinel介绍 1.1是什么 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 用来代替Hystrix Sentinel 具有…

[word] word大小写快捷键是什么? #知识分享#学习方法#笔记

word大小写快捷键是什么&#xff1f; word转换大小写的快捷方式是按“ShiftF3”。设置方法如下&#xff1a; 1、在电脑桌面找到需要转换大小写的文档&#xff0c;右键单击打开它。 2、打开文档之后&#xff0c;在文档里面选中需要转换的段落。 3、选中了之后在键盘里面找到“…

Java:你还在想着考虑使用 tess4j 做文字识别吗?给你看看我的一点实践

需求&#xff1a;删除带有图片水印的图片 语言也设置为中文了&#xff0c;最后给我识别的文字是这样的 | AT V ! w{)" . ) ,/ R Ko 87 ’ 我能理解&#xff0c;毕竟图片很大张&#xff0c;不过不用担心&#xff0c;因为这个水印很有规律&#xff0c;就在右下方裁剪出宽 1…

python 蓝桥杯处理各种输入的数据

文章目录 空格间隔提取数字 空格间隔提取数字 对于以空格间隔的数字&#xff0c;由于输入的形式是字符串&#xff0c;那么就可以使用split 函数进行对输入的一个分隔&#xff0c;然后利用split 函数返回的是分隔之后的一个列表&#xff0c;再利用下标对于每一个部分进行相对应的…

c++ STL less 的视角

c less 函数在不同的地方感觉所起的作用是不一样的&#xff0c; 这中间原因是 less 的视角不一样&#xff0c; 下面尝试给出解释下&#xff0c; 方便记忆 1、 左右视角 符合 排序sort less(value, element&#xff09; less 表示一种 “符合关系“&#xff0c; 表示sort 后…

Git 实战场景过程(工作总结篇)

目录 前言1. Git远程仓库建立分支&#xff0c;本地未显示1.1 问题所示1.2 知识补充 2. Git暂存内容切换分支2.1 问题所示2.2 知识补充 3. Git放弃修改数据3.1 问题所示3.2 知识补充 4. git merge合并查看差异 前言 主要总结工作中的疑惑点&#xff0c;如果你也有相应的场景&am…

1、安全开发-Python爬虫EDUSRC目标FOFA资产Web爬虫解析库

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正 前言&#xff1a; 主要包含对requests库和Web爬虫解析库的使用&#xff0c;python爬虫自动化&#xff0c;批量信息收集 Python开发工具&#xff1a;PyCharm 2022.1 激活破解码_安装教程 (2022年8月25日…

25.泛型

泛型 1.泛型1.1 概述1.2 代码示例 2. 泛型类2.1 概述2.2 代码示例 3. 泛型方法3.1 概述3.2 代码示例 4. 泛型接口4.1 概述4.2 代码示例 5. 泛型特点5.1 概述5.2 代码示例 6. 泛型通配符6.1 概述6.2 代码示例 7. 综合案例8. 注意事项 1.泛型 泛型是Java编程语言的一项重要功能&…

Redis核心技术与实战【学习笔记】 - 15.Redis 缓存的淘汰策略

前言 Redis 缓存使用内存来保存数据&#xff0c;避免业务应用直接从数据库读取数据&#xff0c;可以提升应用的访问速度。但是&#xff0c;我们又没有办法做到把所有的数据都放入缓存&#xff0c;因为这样做的性价比不高&#xff0c;而且缓存也存不下数据库中的所有数据。 例…

《Pandas 简易速速上手小册》第8章:Pandas 高级数据分析技巧(2024 最新版)

文章目录 8.1 使用 apply 和 map 函数8.1.1 基础知识8.1.2 重点案例&#xff1a;客户数据清洗和转换8.1.3 拓展案例一&#xff1a;产品评分调整8.1.4 拓展案例二&#xff1a;地址格式化 8.2 性能优化技巧8.2.1 基础知识8.2.2 重点案例&#xff1a;大型销售数据分析8.2.3 拓展案…

Echarts+Vue 首页大屏静态示例Demo 第三版

效果图: 源码: <template><div class="content bg" style="height: 100vh;overflow-y: auto" :class="{ fullscreen-container: isFullScreen }"><div class="reaDiv" style="height: 10vh"><div…

【华为】GRE VPN 实验配置

【华为】GRE VPN 实验配置 前言报文格式 实验需求配置思路配置拓扑GRE配置步骤R1基础配置GRE 配置 ISP_R2基础配置 R3基础配置GRE 配置 PCPC1PC2 抓包检查OSPF建立GRE隧道建立 配置文档 前言 VPN &#xff1a;&#xff08;Virtual Private Network&#xff09;&#xff0c;即“…

国产飞腾ARM+FPGA电力行业 DCS 联合解决方案

联合解决方案概述 在火电的发展过程中&#xff0c;随着社会对电力资源需求越来越高&#xff0c;以往较为粗放式的发电已经行不通了&#xff0c;需要 更精细化的发电&#xff0c;以达到资源的最大利用。而这种控制都需要靠自动化技术来实现&#xff0c;单纯的人工是达不到这种 …

从第一性原理看大模型Agent技术

引 一个乐观主义者的悲观估计 随着大规模模型技术的兴起&#xff0c;我们正处于一个崭新的智能时代的黎明。我们有一个大胆的预测&#xff0c;未来的5到10年将可能带来一场大变局&#xff1a;99%的开发、设计和文字工作将被AI接管。这不仅仅是一个想象&#xff0c;而是对未来可…

算法学习——华为机考题库2(HJ11 - HJ20)

算法学习——华为机考题库2&#xff08;HJ11 - HJ20&#xff09; HJ11 数字颠倒 描述 输入一个整数&#xff0c;将这个整数以字符串的形式逆序输出 程序不考虑负数的情况&#xff0c;若数字含有0&#xff0c;则逆序形式也含有0&#xff0c;如输入为100&#xff0c;则输出为0…

政安晨的AI笔记——示例演绎OpenAI的ChatGPT与DALL·E提示词总原则(并融合创作一副敦煌飞天仙女图)

ChatGPT是由OpenAI开发的一种基于大规模预训练的语言生成模型。它建立在GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型的基础上&#xff0c;通过大量的无监督学习和生成式任务训练来学习语言的概念和模式。 ChatGPT的原理是基于Transformer模型。Transfo…

java处理ppt方案详解

需求 需要系统中展示的ppt案例有一个动态展示的效果&#xff0c;也就是要有动画的交互&#xff0c;要求支持浏览器直接打开预览 背景 目前已经实现了前端上传pptx文件&#xff0c;后端解析为png的图片&#xff0c;前端掉接口返回对应的图片&#xff0c;模拟播放ppt的效果 各种尝…

Kafka_03_Consumer详解

Kafka_03_Consumer详解 Consumer消费消息订阅/拉取ConsumerRecord 消费位移位移提交位移消费 实现原理RebalanceConsumerInterceptorDeSerializer 多线程消费消费线程处理线程 Consumer Consumer(消费者): 从Partition拉取并消费消息(非线程安全) Topic的Partition在每个消费…