V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
johnkiller
V2EX  ›  问与答

求助 TypeScript 中关于函数参数类型约束的问题

  •  
  •   johnkiller · 2022-04-14 15:45:50 +08:00 · 728 次点击
    这是一个创建于 714 天前的主题,其中的信息可能已经有所发展或是发生改变。
    type Assignable<T, U> = T extends U ? true : false
    
    type Father = (a: Record<string, any>) => void
    type Son = (a: { count: number }) => void
    
    
    type R1 = Assignable<Son, Father> // false
    type R2 = Assignable<Father, Son> // true
    
    type R3 = Assignable<Parameters<Son>, Parameters<Father>> // true
    type R4 = Assignable<{ count: number }, Record<string, any>> // true
    

    { count: number }可以赋给( TypeScript 官方叫它 assignable )类型Record<string, any>我能理解没问题,
    但为什么放到函数的参数里就反过来了呢?
    Son 不应该也是 Father 的子类型吗?

    附上 playgorund: https://reurl.cc/12nVGV

    我的逻辑思维可能太差了💀
    提前感谢点开此贴🙏

    第 1 条附言  ·  2022-04-14 22:02:20 +08:00
    已弄明白,此贴终结。

    如果有同样疑问的 TypeScripter 可以参考前 5 楼回复~
    6 条回复    2022-04-14 21:44:47 +08:00
    noe132
        1
    noe132  
       2022-04-14 16:01:58 +08:00 via Android   ❤️ 2
    这是 Covariance and contravariance 的区别。
    比如我们说 dog extends animal
    如果一个函数调用接受一个 animal ,那么你传 dog 是没有问题的。
    但是如果一个函数调用接受一个 callback ,这个 callback 会收到一个 animal ,如果你传一个收到 dog 的 callback 就不行。因为 callback 的调用方有可能会给你一个 animal ,但 animal 不是 dog 。
    针对类型 T ,如果说 T<dog> extends T<animal> 则 T 是 covarient 。如果 T<animal> extends T<dog>,则 T 是 contravariant 。在你这个例子里,T = (v: T) => void
    noe132
        2
    noe132  
       2022-04-14 16:04:03 +08:00 via Android
    最后一句有些错误,应该是:在你这个例子里,type T<U> = (v: U) => void
    noe132
        3
    noe132  
       2022-04-14 16:09:49 +08:00 via Android   ❤️ 1
    还有一些比较特殊的例子是 invarient 的。最常见的就是可写数组。因为数组的读操作是 corarient ,而写是 contravarient ,2 者结合起来就是 invarient 。
    Array<Dog> 可以 push 一个 GrayHound 进去,也可以 pop 一个 animal 出来,但是不能赋值给 Array<Animal> 或者 Array<GrayHound> 的变量,因为前者可能会 push 一个 dog 进去,后者可能会 pop
    一个 dog 出来。
    chenluo0429
        4
    chenluo0429  
       2022-04-14 16:18:30 +08:00 via Android   ❤️ 1
    举个栗子:
    Farther 类型对应的是可以给所有动物洗澡的机器,参数是所有动物。
    Son 类型是可以给狗洗澡的机器,参数是狗。
    如果你需要一个动物,我可以给你只狗。
    如果你需要一台可以给狗洗澡的机器,我可以给你一台能给所有动物洗澡的机器,但是反过来就不对了。
    johnkiller
        6
    johnkiller  
    OP
       2022-04-14 21:44:47 +08:00
    @chenluo0429
    @enchilada2020
    @noe132

    非常感谢三位,总算看明白了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1389 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 17:35 · PVG 01:35 · LAX 10:35 · JFK 13:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.