【问题标题】:Nested Typescript Map Type嵌套打字稿地图类型
【发布时间】:2021-11-04 21:59:52
【问题描述】:

使用 Typescript 4.5.0,我似乎无法获得要编译的值的类型。对于以下内容:

type foo = 'a' | 'b'

const x: Map<foo, {[key: string]: string}> = new Map([
  ['a', {'ok': 'so'}],
  ['b', {'nah': 'right'}]
])

tsc 吐了

const x: Map<foo, {
    [key: string]: string;
}>
Type 'Map<"a" | "b", { 'ok': string; 'nah'?: undefined; } | { 'nah': string; 'ok'?: undefined; }>' is not assignable to type 'Map<foo, { [key: string]: string; }>'.
  Type '{ 'ok': string; 'nah'?: undefined; } | { 'nah': string; 'ok'?: undefined; }' is not assignable to type '{ [key: string]: string; }'.
    Type '{ 'ok': string; 'nah'?: undefined; }' is not assignable to type '{ [key: string]: string; }'.
      Property ''nah'' is incompatible with index signature.
        Type 'undefined' is not assignable to type 'string'.

这是编译器错误,还是我做错了什么使 Map 的值泛型看起来像联合类型?

A link to the typescript playground

【问题讨论】:

  • 索引签名和undefined 值有点奇怪...在这种情况下,我会说您应该使用{[key: string]: string | undefined} 类型或尝试new Map&lt;foo, {[k: string]: string]}&gt;...但我'我想知道你的用例是什么。我通常使用{[k: string]: SomeType | undefined},因为不太可能每个可能的键都有一个值
  • 据我所知,当types unions of object literal types were improved 时,这将是一个一直到 TS2.7 的错误。
  • 如果您可以扩展您的用例(您打算如何读取/写入此地图?)我可以将这些 cmets 转换为答案。

标签: typescript generics union-types


【解决方案1】:

我很确定这不是错误。 Typescript 将右侧的类型缩小到{ok: string, nah?: undefined} | {ok?: undefined, nah: string},因为您有两个对象缺少另一个对象的属性。如果访问“nah”,则只有“ok”的那个将返回未定义,反之亦然。

这意味着初始类型 {[key: string]: string} 不再有效,因为属性可以返回字符串('so' 和 'right' 是字符串的子类型)或未定义。

解决此问题的最简单方法是使用 Map&lt;foo, {[key: string]: string | undefined}&gt; 允许这些未定义的值。

编辑:更正了推断的类型 - 感谢 jcalz 指出这一点!

【讨论】:

  • 它没有缩小到{ok?: "so", nah?: "right"}。它被推断为{ok: string, nah?: undefined} | {ok?: undefined, nah: string},这是一个不同的类型。
【解决方案2】:

TypeScript 的类型推断有时会有点混乱。它从来都不是完美的,TypeScript 团队不得不做出艰难的选择。 您会得到与您的期望不符的这些选择之一...

您可以通过显式指定泛型类型来进行类型推断:

const x = new Map<foo, {[key: string]: string}>([
  ['a', {'ok': 'so'}],
  ['b', {'nah': 'right'}]
])

【讨论】:

    猜你喜欢
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2018-06-25
    • 2020-11-30
    • 2021-09-10
    • 2021-12-06
    相关资源
    最近更新 更多