V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
zbzzhh
V2EX  ›  JavaScript

请教一个 ts 的问题

  •  
  •   zbzzhh · 2023-09-09 23:28:19 +08:00 · 3389 次点击
    这是一个创建于 467 天前的主题,其中的信息可能已经有所发展或是发生改变。

    type withString = String

    type withNumber = Number

    type emptySet = withString & withNumber

    此时 emptySet 的类型是 never

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

    25 条回复    2023-09-10 21:06:36 +08:00
    KiraMaple
        1
    KiraMaple  
       2023-09-09 23:38:02 +08:00
    never 表示这种情况从来不会发生
    你写一个函数(不标注返回值),函数里面不返回任何东西,直接抛一个异常,你会发现这个函数的类型被自动推导为 never ,意思就是这种情况不会发生,因为这个函数绝对不可能返回任何东西
    在 ts 标准库里面也利用 never 做了很多类型推导之类的,多看看别人或者标准库的 ts 定义很有必要的,能快速学习 ts
    codehz
        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 ,而不管其他的属性
    slmaaw
        3
    slmaaw  
       2023-09-09 23:53:37 +08:00 via Android
    有什么类型既是 string 又是 number 呢? never
    joesonw
        4
    joesonw  
       2023-09-10 00:31:16 +08:00 via iPhone
    withString | withNumber
    leoskey
        5
    leoskey  
       2023-09-10 00:56:43 +08:00
    你的代码表达的是并集,string 与 number 都基础类型,并没有并集
    leoskey
        6
    leoskey  
       2023-09-10 00:57:34 +08:00
    @leoskey 更正,是交集😁
    zbzzhh
        7
    zbzzhh  
    OP
       2023-09-10 01:19:50 +08:00
    @leoskey @slmaaw
    是的,是我表达得有问题,我问的是图片里的为什么有交集
    zbzzhh
        8
    zbzzhh  
    OP
       2023-09-10 01:21:23 +08:00
    string 和 number 没有并集我是可以理解的,只是图片里有并集我是不理解
    chnwillliu
        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 的缘故,自然很轻松推导出交集的类型。
    chnwillliu
        10
    chnwillliu  
       2023-09-10 05:24:06 +08:00 via Android
    集合 A : 有羽毛的动物 ({a: string})
    集合 B : 两只脚的动物 ({b: number})

    A 和 B 的交集是空集么?不是对吧。AB 在不同方面描述这个东西,交集就是属性叠加,对类型进一步约束。
    zhy0216
        11
    zhy0216  
       2023-09-10 07:59:08 +08:00 via Android
    对 interface 理解没到位
    只要有属性 a 就是集合 A
    只要有属性 b 就是集合 B
    那既有 a 又有 b 可不是 A n B 嘛
    slmaaw
        12
    slmaaw  
       2023-09-10 09:15:27 +08:00 via Android
    @zbzzhh 我仔细看了一下你的类型 是 String 和 Number 大写开头意味着是 Object 对象而非基本类型 如果不考虑这些对象实际返回的是基本类型 单纯是两个对象的话 确实是图中那样 可以存在交集 但这个交集实际是两个基础类型相交 所以是 never 但如果你吧这两个对象魔改了 那就有可能有交集
    说的有点绕 感觉应该是这样
    jinliming2
        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 } 就满足条件。
    jadehare
        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 ,只不过没声明而已。所以两个对象看起来只有一个属性,但是相交后反而变成两个属性了。我猜图里面应该是这个意思。
    darkengine
        15
    darkengine  
       2023-09-10 14:58:50 +08:00   ❤️ 1
    因为你写的代码里的类型是 String, Number

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

    String 和{a: String}完全不是一个类型
    DeltaSix
        16
    DeltaSix  
       2023-09-10 15:03:49 +08:00
    你把两个 type alias 并一块然后和图里的两个 interface 比,关键楼上还有一堆人分析的头头是道,实属绷不住了,这就是 V2EX 人均看不起切图仔
    cheese
        17
    cheese  
       2023-09-10 15:21:10 +08:00
    @DeltaSix #16 虽然但是,我看了下,好像楼上表达的都是对的,只是有人没回答楼主问题
    zhaomeicheng
        18
    zhaomeicheng  
       2023-09-10 15:58:36 +08:00
    op 是在学习 https://type-level-typescript.com/这个吗 感觉好贵 只有前四章免费
    zbzzhh
        19
    zbzzhh  
    OP
       2023-09-10 16:18:35 +08:00 via iPhone
    @zhaomeicheng 是的,我就看免费的前 4 章,教程挺好的
    darkengine
        20
    darkengine  
       2023-09-10 16:59:21 +08:00
    @cheese 因为他的问题是错的
    TunkShif
        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 属性的全体对象
    mingdongshensen
        22
    mingdongshensen  
       2023-09-10 18:35:38 +08:00
    你的情况是原始类型,不同原始类型之间一般都是互斥的,但截图同为对象类型,可以同时满足
    Belmode
        23
    Belmode  
       2023-09-10 20:32:40 +08:00
    GPT 是这么回复的
    kayanouriko
        24
    kayanouriko  
       2023-09-10 20:41:55 +08:00
    感谢 op 提的这个问题, 根据楼上的回复搜了一下关键词 ( 结构类型系统 / Structural Type System ) 扩展了知识面.
    PTLin
        25
    PTLin  
       2023-09-10 21:06:36 +08:00
    系统自带的,非用户结构化定义的类型需要特殊的去记对应的规则,类似的还有 keyof any = string | number | symbol
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1336 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 17:43 · PVG 01:43 · LAX 09:43 · JFK 12:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.