typescript - 打字稿地图> “没有重载匹配这个调用”,但我不明白为什么?
问题描述
我正在用 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)
}
我真的不明白这怎么可能?
解决方案
非常有趣的问题。这是解决方案:
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
您不能分配fst
给scd
,但是,如果您将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你可能会发现这个答案也很有趣
我对批评持开放态度,所以请随时指出我的错误。谢谢
推荐阅读
- mfc - 检测是否使用 MFC 安装了 Opera 浏览器
- vue.js - 除了单击的按钮外,如何禁用按钮?
- c# - Is there any Solution for my code problem in webbrowser to identify between Select tag and option
- react-native - react-navigation 和 api 调用的 Redux 错误
- raku - 在 perl6 语法中放松空格的最佳方法是什么?
- node.js - 多次请求时出现内部服务器错误,nginx + node.js + pm2
- java - 在Spring Boot中没有外键的Rest api返回项
- docker - 如何与 docker 机器共享本地主机的文件
- sql - 如何在医院数据库中创建触发器?
- wpf - 我可以使用 ViewBox 作为 WPF 中图像的源吗?