请教一个 ts 的问题

2023-09-09 23:28:19 +08:00
 zbzzhh

type withString = String

type withNumber = Number

type emptySet = withString & withNumber

此时 emptySet 的类型是 never

那请问下图为何类型 a 跟 b 是有相交的部分?我理解是 never 。

3398 次点击
所在节点    JavaScript
25 条回复
KiraMaple
2023-09-09 23:38:02 +08:00
never 表示这种情况从来不会发生
你写一个函数(不标注返回值),函数里面不返回任何东西,直接抛一个异常,你会发现这个函数的类型被自动推导为 never ,意思就是这种情况不会发生,因为这个函数绝对不可能返回任何东西
在 ts 标准库里面也利用 never 做了很多类型推导之类的,多看看别人或者标准库的 ts 定义很有必要的,能快速学习 ts
codehz
2023-09-09 23:44:03 +08:00
ts 的&魔法比较多,对于 object 的情况就是开这个特例的。。。不过也可以说是 ts 的 object 类型本身就比较奇特
{a: string}的含义是一个 object 有一个叫做 a 的 string 属性——也就是不管它有没有别的属性,别的属性有什么类型
因此{a: string}和{b:number}的交集,自然是增强约束——即要求同时有 a 和 b 属性,类型分别为 string 和 number ,而不管其他的属性
slmaaw
2023-09-09 23:53:37 +08:00
有什么类型既是 string 又是 number 呢? never
joesonw
2023-09-10 00:31:16 +08:00
withString | withNumber
leoskey
2023-09-10 00:56:43 +08:00
你的代码表达的是并集,string 与 number 都基础类型,并没有并集
leoskey
2023-09-10 00:57:34 +08:00
@leoskey 更正,是交集😁
zbzzhh
2023-09-10 01:19:50 +08:00
@leoskey @slmaaw
是的,是我表达得有问题,我问的是图片里的为什么有交集
zbzzhh
2023-09-10 01:21:23 +08:00
string 和 number 没有并集我是可以理解的,只是图片里有并集我是不理解
chnwillliu
2023-09-10 05:14:01 +08:00
如果 C 是 A 的子集,C 又是 B 的子集,C 必然是 A 交 B 或其子集。A 和 B 的交集就是既满足 A 又满足 B ,duck type 的缘故,自然很轻松推导出交集的类型。
chnwillliu
2023-09-10 05:24:06 +08:00
集合 A : 有羽毛的动物 ({a: string})
集合 B : 两只脚的动物 ({b: number})

A 和 B 的交集是空集么?不是对吧。AB 在不同方面描述这个东西,交集就是属性叠加,对类型进一步约束。
zhy0216
2023-09-10 07:59:08 +08:00
对 interface 理解没到位
只要有属性 a 就是集合 A
只要有属性 b 就是集合 B
那既有 a 又有 b 可不是 A n B 嘛
slmaaw
2023-09-10 09:15:27 +08:00
@zbzzhh 我仔细看了一下你的类型 是 String 和 Number 大写开头意味着是 Object 对象而非基本类型 如果不考虑这些对象实际返回的是基本类型 单纯是两个对象的话 确实是图中那样 可以存在交集 但这个交集实际是两个基础类型相交 所以是 never 但如果你吧这两个对象魔改了 那就有可能有交集
说的有点绕 感觉应该是这样
jinliming2
2023-09-10 10:50:48 +08:00
这个是字面意思吧?& 就是与/且 的意思,就是结果类型要同时满足左右两个类型。
A&B=既是 A ,并且又是 B 。
什么类型“既是 String ,又是 Number”呢?好像没有吧?
但什么类型“既是 { a: string },又是 { b: number }”呢?{ a: string, b: number } 就满足条件。
jadehare
2023-09-10 13:19:56 +08:00
交集这部分不应该按类型来理解了,ts 里统一是 object 类,所以不会是 never 。图中这个情况按正常集合理解其实更像是并集,只不过 ts 的类型是可以魔改的 A = {a} 但是你也可以通过 A["b"]取到 b 只不过是 undefined 。或者可以理解成 A = {a:string,b:any}, B = {a:any,b:number},甚至可以有 c,d,e ,只不过没声明而已。所以两个对象看起来只有一个属性,但是相交后反而变成两个属性了。我猜图里面应该是这个意思。
darkengine
2023-09-10 14:58:50 +08:00
因为你写的代码里的类型是 String, Number

图里的两个类型是{a: String}和{b: Number}

String 和{a: String}完全不是一个类型
DeltaSix
2023-09-10 15:03:49 +08:00
你把两个 type alias 并一块然后和图里的两个 interface 比,关键楼上还有一堆人分析的头头是道,实属绷不住了,这就是 V2EX 人均看不起切图仔
cheese
2023-09-10 15:21:10 +08:00
@DeltaSix #16 虽然但是,我看了下,好像楼上表达的都是对的,只是有人没回答楼主问题
zhaomeicheng
2023-09-10 15:58:36 +08:00
op 是在学习 https://type-level-typescript.com/这个吗 感觉好贵 只有前四章免费
zbzzhh
2023-09-10 16:18:35 +08:00
@zhaomeicheng 是的,我就看免费的前 4 章,教程挺好的
darkengine
2023-09-10 16:59:21 +08:00
@cheese 因为他的问题是错的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/972362

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX