嵌套打字稿地图类型

时间:2019-07-20 21:46:34

标签: typescript generics union-types

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

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

2 个答案:

答案 0 :(得分:0)

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

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

解决这个问题的最简单方法是使用Map<foo, {[key: string]: string | undefined}>来允许这些未定义的值。

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

答案 1 :(得分:-1)

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

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

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