在使用Typescript的es6 Map中使用泛型

时间:2017-07-20 19:39:51

标签: typescript generics ecmascript-6

我在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]>'.

2 个答案:

答案 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()]
]);