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

请教一个 ts 的问题

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

    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 更正,是交集
    Thunderaxe
        7
    Thunderaxe  
    OP
       2023-09-10 01:19:50 +08:00
    @leoskey @slmaaw
    是的,是我表达得有问题,我问的是图片里的为什么有交集
    Thunderaxe
        8
    Thunderaxe  
    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 虽然但是,我看了下,好像楼上表达的都是对的,只是有人没回答楼主问题
    nazalewoyuanyi
        18
    nazalewoyuanyi  
       2023-09-10 15:58:36 +08:00
    op 是在学习 https://type-level-typescript.com/这个吗 感觉好贵 只有前四章免费
    Thunderaxe
        19
    Thunderaxe  
    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     Solana     779 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 21:13 PVG 05:13 LAX 13:13 JFK 16:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86