我在Typescript 2.0中有一个项目,我使用es6
作为我的模块,包含了lib es2017
,所以我可以使用地图。除了我似乎需要做一些不必要的演员表之外,我已经完成了所有工作。
static readonly gameStateMap: Map<GameState, Phaser.State> = new Map([
[GameState.PONG, new PongState() as Phaser.State],
[GameState.BREAKOUT, new BreakoutState() as Phaser.State]
]);
为什么我需要将它们投射到Phaser.State
?由于它们都直接延伸Phaser.State
我以为我应该能够将它们牢牢地粘在地图上而没有问题。
我想也许我只需要优化我的泛型声明,所以我尝试了:
Map<GameState, V extends Phaser.State>
。
我在Typescript's generics docs中看到了这种语法。
但它不起作用。这是ES6通用的,这是我的问题吗?如何解决此问题而不需要进行投射?
此外,只有在相关类具有不同属性时才会出现此问题。错误是:
error TS2345: Argument of type '((GameState | PongState)[] | (GameState | BreakoutState)[])[]' is not assignable to parameter of type 'Iterable<[GameState, State]>'.
答案 0 :(得分:2)
如果你的系统有问题。您需要提供更多信息。
它正在playground
中工作enum GameState {
PONG,
BREAKOUT
}
namespace Phaser {
export interface State { }
}
class PongState implements Phaser.State { }
class BreakoutState implements Phaser.State { }
let gameStateMap: Map<GameState, Phaser.State> = new Map([
[GameState.PONG, new PongState()],
[GameState.BREAKOUT, new BreakoutState()]
]);
更新:
您面临的问题是您手动声明类型并依赖推断。推断只能做很多事情。在这种情况下,两个内部数组不能推断为共同类型,因此它们最终为[{}, {}]
。
解决方案是直接使用泛型:
enum GameState {
PONG,
BREAKOUT
}
namespace Phaser {
export interface State { }
}
class PongState implements Phaser.State { a: string }
class BreakoutState implements Phaser.State { b: string }
let gameStateMap = new Map<GameState, Phaser.State>([
[GameState.PONG, new PongState()],
[GameState.BREAKOUT, new BreakoutState()]
]);
答案 1 :(得分:1)
当你以这种方式写作时
let gameStateMap: Map<GameState, Phaser.State> = new Map(...)
编译器首先尝试推断new Map
的类型,然后检查它是否与为gameStateMap
声明的类型兼容。
在您的情况下,当涉及具有不同类型的元素的数组时,编译器无法为它们推断公共类型并使用union类型(Map
参数的预期类型显然是[GameState, Phaser.State][]
)。
编译器需要一些帮助,您可以通过向Map
构造函数提供显式泛型参数来提供它,然后您可以省略gameStateMap
的显式类型声明:
enum GameState { PONG, BREAKOUT };
namespace Phaser {
export interface State { }
}
class PongState implements Phaser.State { a: string }
class BreakoutState implements Phaser.State { b: string}
let gameStateMap = new Map< GameState, Phaser.State > ([
[GameState.PONG, new PongState()],
[GameState.BREAKOUT, new BreakoutState()]
]);