typescript - 当键具有多种类型时,如何在构造函数中设置类型化 Map 的初始值

标签 typescript

我想创建一个 Map,其中的键可以是 numberstring。我想用构造函数中的值初始化它。有些条目有一个 number 键,有些有一个 string 键。

但是我收到一个 typescript 错误。这是一个 TypeScript 错误,还是我做错了什么?

type MyMap = Map<string | number, string>;

// Errors, incorrectly?
const myMapWithMixedKeys: MyMap = new Map([
  ['abc', 'String key'],
  [123, 'Number key']
]);

// All fine
myMapWithMixedKeys.set('abcd', 'String key');
myMapWithMixedKeys.set(1234, 'Number key');

const myMapStrings: MyMap = new Map([
  ['abc', 'String key'],
  ['abcd', 'String key']
]);

const myMapNumbers: MyMap = new Map([
  [123, 'Number key'],
  [1234, 'Number key']
]);

错误:

No overload matches this call.
  Overload 1 of 3, '(iterable: Iterable<readonly [string, string]>): Map<string, string>', gave the following error.
    Argument of type '([string, string] | [number, string])[]' is not assignable to parameter of type 'Iterable<readonly [string, string]>'.
      Types of property '[Symbol.iterator]' are incompatible.
        Type '() => IterableIterator<[string, string] | [number, string]>' is not assignable to type '() => Iterator<readonly [string, string], any, undefined>'.
          Type 'IterableIterator<[string, string] | [number, string]>' is not assignable to type 'Iterator<readonly [string, string], any, undefined>'.
            Types of property 'next' are incompatible.
              Type '(...args: [] | [undefined]) => IteratorResult<[string, string] | [number, string], any>' is not assignable to type '(...args: [] | [undefined]) => IteratorResult<readonly [string, string], any>'.
                Type 'IteratorResult<[string, string] | [number, string], any>' is not assignable to type 'IteratorResult<readonly [string, string], any>'.
                  Type 'IteratorYieldResult<[string, string] | [number, string]>' is not assignable to type 'IteratorResult<readonly [string, string], any>'.
                    Type 'IteratorYieldResult<[string, string] | [number, string]>' is not assignable to type 'IteratorYieldResult<readonly [string, string]>'.
                      Type '[string, string] | [number, string]' is not assignable to type 'readonly [string, string]'.
                        Type '[number, string]' is not assignable to type 'readonly [string, string]'.
                          Types of property '0' are incompatible.
                            Type 'number' is not assignable to type 'string'.
  Overload 2 of 3, '(entries?: readonly (readonly [string, string])[] | null | undefined): Map<string, string>', gave the following error.
    Argument of type '([string, string] | [number, string])[]' is not assignable to parameter of type 'readonly (readonly [string, string])[]'.
      Type '[string, string] | [number, string]' is not assignable to type 'readonly [string, string]'.
        Type '[number, string]' is not assignable to type 'readonly [string, string]'.ts(2769)

最佳答案

问题是 TS 通过其第一个值推断 new Map() 的类型。 即使您只写 let m = new Map([[1, 1], ['2', 2]]) 而没有任何输入,也会发生这种情况。

(顺便说一句:当您编写类似 let a = new Array(1, '2') 的代码时,它也会发生在数组中)。

要解决这个问题,您应该强制 TS 理解 Map 的类型是联合类型。我知道有两种方法可以做到这一点:

const myMapWithMixedKeys: MyMap = new Map<string | number, string>([
  ['abc', 'String key'],
  [123, 'Number key']
]);

或者:

const myMapWithMixedKeys: MyMap = new Map([
  ['abc' as string | number, 'String key'],
  [123, 'Number key']
]);

参见 Playground

编辑:IMO,我找到了更好的解决方案。

代替:

type MyMap = Map<string | number, string>;

写:

class MyMap extends Map<string | number, string> { }

现在一切正常。参见 updated Playground

关于typescript - 当键具有多种类型时,如何在构造函数中设置类型化 Map 的初始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60422719/

相关文章:

typescript - 如何在数组中只允许唯一的字符串文字

javascript - 选择正确的数据结构 : boolean check vs array . include(性能 vs 冗余)

javascript - 如何使用网络蓝牙解析 "Indoor Bike Data"

javascript - RxJS - 无限滚动 - 在上一个未到达时发送请求

typescript - 如何在当前的 TypeScript 中使用 Bluebird?

reactjs - 带有反应 Spring 的 typescript 。类型 'interpolate' 上不存在属性 'number'

angular - 如何手动重新渲染组件 Angular 5

TypeScript 不验证从 Promise 返回的值的通用类型?

Typescript 如何安全地将枚举转换为另一个枚举?

typescript - 如何在 typescript 中的编译器转换器上将标识符与现有符号绑定(bind)?