type withString = String
type withNumber = Number
type emptySet = withString & withNumber
此时 emptySet 的类型是 never
那请问下图为何类型 a 跟 b 是有相交的部分?我理解是 never 。
1
KiraMaple 2023-09-09 23:38:02 +08:00
never 表示这种情况从来不会发生
你写一个函数(不标注返回值),函数里面不返回任何东西,直接抛一个异常,你会发现这个函数的类型被自动推导为 never ,意思就是这种情况不会发生,因为这个函数绝对不可能返回任何东西 在 ts 标准库里面也利用 never 做了很多类型推导之类的,多看看别人或者标准库的 ts 定义很有必要的,能快速学习 ts |
2
codehz 2023-09-09 23:44:03 +08:00 2
ts 的&魔法比较多,对于 object 的情况就是开这个特例的。。。不过也可以说是 ts 的 object 类型本身就比较奇特
{a: string}的含义是一个 object 有一个叫做 a 的 string 属性——也就是不管它有没有别的属性,别的属性有什么类型 因此{a: string}和{b:number}的交集,自然是增强约束——即要求同时有 a 和 b 属性,类型分别为 string 和 number ,而不管其他的属性 |
3
slmaaw 2023-09-09 23:53:37 +08:00 via Android
有什么类型既是 string 又是 number 呢? never
|
4
joesonw 2023-09-10 00:31:16 +08:00 via iPhone
withString | withNumber
|
5
leoskey 2023-09-10 00:56:43 +08:00
你的代码表达的是并集,string 与 number 都基础类型,并没有并集
|
8
zbzzhh OP string 和 number 没有并集我是可以理解的,只是图片里有并集我是不理解
|
9
chnwillliu 2023-09-10 05:14:01 +08:00 via Android
如果 C 是 A 的子集,C 又是 B 的子集,C 必然是 A 交 B 或其子集。A 和 B 的交集就是既满足 A 又满足 B ,duck type 的缘故,自然很轻松推导出交集的类型。
|
10
chnwillliu 2023-09-10 05:24:06 +08:00 via Android
集合 A : 有羽毛的动物 ({a: string})
集合 B : 两只脚的动物 ({b: number}) A 和 B 的交集是空集么?不是对吧。AB 在不同方面描述这个东西,交集就是属性叠加,对类型进一步约束。 |
11
zhy0216 2023-09-10 07:59:08 +08:00 via Android
对 interface 理解没到位
只要有属性 a 就是集合 A 只要有属性 b 就是集合 B 那既有 a 又有 b 可不是 A n B 嘛 |
12
slmaaw 2023-09-10 09:15:27 +08:00 via Android
@zbzzhh 我仔细看了一下你的类型 是 String 和 Number 大写开头意味着是 Object 对象而非基本类型 如果不考虑这些对象实际返回的是基本类型 单纯是两个对象的话 确实是图中那样 可以存在交集 但这个交集实际是两个基础类型相交 所以是 never 但如果你吧这两个对象魔改了 那就有可能有交集
说的有点绕 感觉应该是这样 |
13
jinliming2 2023-09-10 10:50:48 +08:00 via iPhone 1
这个是字面意思吧?& 就是与/且 的意思,就是结果类型要同时满足左右两个类型。
A&B=既是 A ,并且又是 B 。 什么类型“既是 String ,又是 Number”呢?好像没有吧? 但什么类型“既是 { a: string },又是 { b: number }”呢?{ a: string, b: number } 就满足条件。 |
14
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 ,只不过没声明而已。所以两个对象看起来只有一个属性,但是相交后反而变成两个属性了。我猜图里面应该是这个意思。
|
15
darkengine 2023-09-10 14:58:50 +08:00 1
因为你写的代码里的类型是 String, Number
图里的两个类型是{a: String}和{b: Number} String 和{a: String}完全不是一个类型 |
16
DeltaSix 2023-09-10 15:03:49 +08:00
你把两个 type alias 并一块然后和图里的两个 interface 比,关键楼上还有一堆人分析的头头是道,实属绷不住了,这就是 V2EX 人均看不起切图仔
|
18
zhaomeicheng 2023-09-10 15:58:36 +08:00
op 是在学习 https://type-level-typescript.com/这个吗 感觉好贵 只有前四章免费
|
19
zbzzhh OP @zhaomeicheng 是的,我就看免费的前 4 章,教程挺好的
|
20
darkengine 2023-09-10 16:59:21 +08:00
@cheese 因为他的问题是错的
|
21
TunkShif 2023-09-10 17:47:20 +08:00 2
假定有 type A = { foo: string }, type B = { bar: string }, type C = A & B, const obj = { foo: "foo", bar: "bar" }
那么 let a: A = obj, let b: B = obj, let c: C = obj 都是成立的 即 obj 这个值的类型既可以是 A ,也可以是 B ,还可以是 C ,[TS Playground]( https://www.typescriptlang.org/play?#code/C4TwDgpgBAglC8UDeAoKUBmB7LAuKAzsAE4CWAdgOYoC+KKokUAQgsmlAEYCGx+RZKrXqNoAYTZwAZC3oBjLOSJQsnAFZtU6bHigAiHXoA0HHn31njp7gC98enjb3CUAGwjAo3fHESq1bh5c+Kx+6oGecvgSYWpAA) 因为 TypeScript 的类型系统是 [structural typing]( https://www.typescriptlang.org/play#example/structural-typing) 的,类型 type A = { foo: string } 并不是表示仅有 foo 这一个属性的对象才属于该类型,而是表示只要某对象含有 foo 这一个属性便属于该类型 所以属于类型 A 的值为含有 foo 属性的全体对象,属于类型 B 的值为含有 bar 属性的全体对象,那么属于 A 和 B 的交集类型的值则为同时含有 foo 和 bar 属性的全体对象 |
22
mingdongshensen 2023-09-10 18:35:38 +08:00
你的情况是原始类型,不同原始类型之间一般都是互斥的,但截图同为对象类型,可以同时满足
|
23
Belmode 2023-09-10 20:32:40 +08:00
|
24
kayanouriko 2023-09-10 20:41:55 +08:00
感谢 op 提的这个问题, 根据楼上的回复搜了一下关键词 ( 结构类型系统 / Structural Type System ) 扩展了知识面.
|
25
PTLin 2023-09-10 21:06:36 +08:00
系统自带的,非用户结构化定义的类型需要特殊的去记对应的规则,类似的还有 keyof any = string | number | symbol
|