Nested Typescript Map Type

徘徊边缘 提交于 2021-01-28 22:13:57

问题


With Typescript 3.5.1, I can't seem to get the type of values to compile. For the following:

type foo = 'a' | 'b'

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

tsc barfs up

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'.

Is this a compiler bug, or am I doing something wrong to make the Map's value generic look like a union type?

A link to the typescript playground


回答1:


I'm pretty sure this is not a bug. Typescript narrows the type of your right side down to {ok: string, nah?: undefined} | {ok?: undefined, nah: string}, since you have two objects that are missing the property of the other. The one that has only "ok" will return undefined if "nah" is accessed and vice-versa.

This means that the initial type {[key: string]: string} is not valid anymore, because the properties can either return a string ('so' and 'right' are subtypes of string) or undefined.

The simpliest way around this is to allow these undefined values by using Map<foo, {[key: string]: string | undefined}>.

Edit: Corrected the inferred type - thanks to jcalz for pointing that out!




回答2:


TypeScript's type inference can be a bit confusing sometimes. It is never perfect and the TypeScript team had to make hard choices. You get one of these choices that does not match your expectations...

You can get ride of type inference by explicitly specifying the generic types:

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


来源:https://stackoverflow.com/questions/57128823/nested-typescript-map-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!