【问题标题】:TypeScript union of type is resolved as intersection of types类型的 TypeScript 联合被解析为类型的交集
【发布时间】:2019-12-14 19:42:00
【问题描述】:

我有这个sn-p

class J {
  constructor(public foo: number) {}
}

class B {
 constructor(public bar: string) {}
}

interface Cache {
 json?: J;
 binary?: B;
}

function test(key: "json" | "binary", data: J | B, obj: Cache) {
  obj[key] = data;
}

如果您在https://www.typescriptlang.org/play/ 中尝试此代码,obj[key] = data; 行会出现以下错误

键入'J | B' 不可分配给类型 'J & B'。 类型“J”不可分配给类型“J & B”。 类型“J”中缺少属性“bar”,但类型“B”中需要。

显然我缺少一些东西,但我不知道是什么。有什么想法吗?

【问题讨论】:

    标签: typescript typescript3.0 union-types


    【解决方案1】:

    key 和data 之间没有关系,所以你可以用test( "json", new B()) 调用测试,分配将无效。

    如果您使用泛型类型参数(我们称之为K)作为键并将data 键入为Cache[K],打字稿将允许赋值。 (尽管它仍然不是 100% 类型安全的,因为 K 可能是一个联合,并且可能会发生与上述相同的问题):

    class J {
      constructor(public foo: number) {}
    }
    
    class B {
     constructor(public bar: string) {}
    }
    
    interface Cache {
     json?: J;
     binary?: B;
    }
    
    function test<K extends keyof Cache>(key: K, data: Cache[K], obj: Cache) {
      obj[key] = data;
    }
    

    Play

    【讨论】:

      【解决方案2】:

      Typescript 无法判断您尝试更新 Cache 的哪个属性,并且当有疑问时,他认为您尝试插入的值应该能够同时适合两者。其中J | B can't.

      您可以稍微更改您的 test 函数签名以使用 Partial

      function test(update: Partial<Cache>, obj: Cache) {
          Object.assign(obj, update);
      }
      

      这样,Typescript 可以确保您传递给它的键/值对对 Cache 类有效。

      【讨论】:

      • @rocketer Partial 在 IMO 是一个更好的选择。如果您没有其他限制,我会这样做。
      • @TitianCernicova-Dragomir 我同意,在这种情况下我也不想使用泛型
      猜你喜欢
      • 1970-01-01
      • 2020-07-31
      • 2019-03-26
      • 2018-10-26
      • 2021-09-03
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多