> “没有重载匹配这个调用”,但我不明白为什么?,typescript,dictionary,enums"/>

首页 > 解决方案 > 打字稿地图> “没有重载匹配这个调用”,但我不明白为什么?

问题描述

我正在用 Typescript 创建一个棋盘游戏。我在其中声明以下内容:

export enum PieceType {
    PAWN,
    KNIGHT2,
    KNIGHT4,
    WIZARD,
    KING
}

export class Board {
    // ...
    private takeRules: Map<PieceType, Set<PieceType>> = new Map([
        [PieceType.PAWN, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD])],
        [PieceType.KNIGHT2, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD, PieceType.KING])],
        [PieceType.KNIGHT4, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD, PieceType.KING])],
        [PieceType.KING, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])]
    ]);
    private enchantRules: Map<PieceType, Set<PieceType>> = new Map([
        [PieceType.WIZARD, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])],
        [PieceType.KING, new Set([PieceType.WIZARD])]
    ]);
    // ...
}

此错误如下:

[tsl] ERROR in ./src/board.ts(28,60)
      TS2769: No overload matches this call.
  Overload 1 of 3, '(iterable: Iterable<readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>]>): Map<PieceType.WIZARD | PieceType.KING, Set<...>>', gave the following error.
    Argument of type '([PieceType.WIZARD, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>] | [PieceType.KING, Set<PieceType.WIZARD>])[]' is not assignable to parameter of type 'Iterable<readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>]>'.
      The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
        Type 'IteratorResult<[PieceType.WIZARD, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>] | [PieceType.KING, Set<PieceType.WIZARD>], any>' is not assignable to type 'IteratorResult<readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>], any>'.
          Type 'IteratorYieldResult<[PieceType.WIZARD, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>] | [PieceType.KING, Set<PieceType.WIZARD>]>' is not assignable to type 'IteratorResult<readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>], any>'.
            Type 'IteratorYieldResult<[PieceType.WIZARD, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>] | [PieceType.KING, Set<PieceType.WIZARD>]>' is not assignable to type 'IteratorYieldResult<readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>]>'.
              Type '[PieceType.WIZARD, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>] | [PieceType.KING, Set<PieceType.WIZARD>]' is not assignable to type 'readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>]'.
                Type '[PieceType.KING, Set<PieceType.WIZARD>]' is not assignable to type 'readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>]'.
                  Types of property '1' are incompatible.
                    Type 'Set<PieceType.WIZARD>' is not assignable to type 'Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>'.
                      Type 'PieceType.WIZARD' is not assignable to type 'PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4'.
  Overload 2 of 3, '(entries?: readonly (readonly [PieceType.WIZARD | PieceType.KING, Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>])[]): Map<PieceType.WIZARD | PieceType.KING, Set<...>>', gave the following error.
    Type 'Set<PieceType.WIZARD>' is not assignable to type 'Set<PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4>'.

如果我将第二张地图放在评论中:没问题。如果我在第二张地图的最后一行省略了向导枚举:没问题。我什至可以毫无问题地将省略的值放入使用构造函数中。例如

    private takeRules: Map<PieceType, Set<PieceType>> = new Map([
        [PieceType.PAWN, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD])],
        [PieceType.KNIGHT2, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD, PieceType.KING])],
        [PieceType.KNIGHT4, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD, PieceType.KING])],
        [PieceType.KING, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])]
    ]);
    private enchantRules: Map<PieceType, Set<PieceType>> = new Map([
        [PieceType.WIZARD, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])],
        [PieceType.KING, new Set([])]
    ]);

   // ...

    constructor() {
        // ...
        this.enchantRules.get(PieceType.KING).add(PieceType.WIZARD)
    }

我真的不明白这怎么可能?

标签: typescriptdictionaryenums

解决方案


非常有趣的问题。这是解决方案:

export enum PieceType {
    PAWN,
    KNIGHT2,
    KNIGHT4,
    WIZARD,
    KING
}

export class Board {
    // ...
    private takeRules = new Map<PieceType, Set<PieceType>>([
        [PieceType.PAWN, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD])],
        [PieceType.KNIGHT2, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD, PieceType.KING])],
        [PieceType.KNIGHT4, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4, PieceType.WIZARD, PieceType.KING])],
        [PieceType.KING, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])]
    ]);
    private enchantRules = new Map<PieceType, Set<PieceType>>([
        [PieceType.WIZARD, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])],
        [PieceType.KING, new Set([PieceType.WIZARD])]
    ])
}

我只是定义了泛型Map而不是定义整个类型:new Map<PieceType, Set<PieceType>>

但主要问题是,为什么会发生错误?

我们来分析一下:

   private enchantRules: Map<PieceType, Set<PieceType>> = new Map([
        [PieceType.WIZARD, new Set([PieceType.PAWN, PieceType.KNIGHT2, PieceType.KNIGHT4])],
        [PieceType.KING, new Set([PieceType.WIZARD])]
    ]);

如果你把类型定义放在符号Map<PieceType, Set<PieceType>>之前equal,TS 会尝试推断这些类型。因此,如果您输入一些PieceType以前实体中不存在的枚举值,它将引发错误。

看一个更简单的例子:

type Fst = PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4
type Scd = PieceType.WIZARD

let fst: Fst = PieceType.PAWN;
let scd: Scd = PieceType.WIZARD;

scd = fst; // error

您不能分配fstscd,但是,如果您将PAWN枚举类型添加到Scd类型,它将起作用:

type Fst = PieceType.PAWN | PieceType.KNIGHT2 | PieceType.KNIGHT4
type Scd = PieceType.WIZARD | PieceType.PAWN

let fst: Fst = PieceType.PAWN;
let scd: Scd = PieceType.WIZARD;

scd = fst; // ok

让我们回到我们的问题。因为WIZARD没有在第一个 Map 值中定义V,所以您根本无法使用 WIZARD。

所以,我相信你应该坚持使用明确的泛型类型定义,而不是直接在变量定义附近定义你的类型。

PS你可能会发现这个答案也很有趣

我对批评持开放态度,所以请随时指出我的错误。谢谢


推荐阅读