2017-07-20 2 views
1

Ich habe ein Projekt in Typescript 2.0 und ich verwende es6 als mein Modul, mit der Lib es2017 enthalten, so dass ich Karten verwenden kann. Ich habe alles in Ordnung, außer dass ich unnötige Zaubersprüche brauche.Verwendung von Generics in es6 Karte mit Typescript

static readonly gameStateMap: Map<GameState, Phaser.State> = new Map([ 
    [GameState.PONG, new PongState() as Phaser.State], 
    [GameState.BREAKOUT, new BreakoutState() as Phaser.State] 
]); 

Warum muss ich sie Phaser.State werfen? Da sie beide direkt erweitern Phaser.State Ich dachte, ich sollte in der Lage sein, sie einfach in der Karte ohne Probleme zu haften.

Ich dachte, vielleicht brauchte nur ich meine Generika Erklärung zu verfeinern, so dass ich versuchte:

Map<GameState, V extends Phaser.State>.

Ich sehe diese Syntax in Typescript's generics docs verwendet.

Aber es funktioniert nicht. Ist das ein ES6 Generic und das ist mein Problem? Wie kann ich das beheben, um nicht zu casten?

Dieses Problem tritt auch nur auf, wenn die fraglichen Klassen unterschiedliche Eigenschaften haben. Der Fehler ist:

error TS2345: Argument of type '((GameState | PongState)[] | (GameState | BreakoutState)[])[]' is not assignable to parameter of type 'Iterable<[GameState, State]>'. 

Antwort

2

Es ist etwas falsch, wenn Ihr System. Sie müssen mehr Informationen bereitstellen.

Es ist in der 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()] 
]); 

UPDATE arbeiten: Das Problem, das Sie Gesicht ist, dass Sie Typ manuell und stützen sich auf Folgern erklären. Die Schlussfolgerung kann nur so viel bewirken. In diesem Fall können die zwei inneren Array nicht zu einem gemeinsamen Typ abgeleitet werden, so dass sie als [{}, {}] endete. Die Lösung ist die generische direkt zu verwenden:

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()] 
]); 
+0

Ich spielte mit dem Spielplatz zu machen Es ähnelt mehr meinem Code und konnte das Problem neu erstellen, indem ich die Klassendeklarationen folgendermaßen ändere: 'Klasse PongState implementiert Phaser.State {stuff: string; } '' Klasse BreakoutState implementiert Phaser.State {notStuff: number; } '. Es scheint, das Problem tritt nur auf, wenn die Klassen unterschiedliche Eigenschaften enthalten. – CorayThan

1

Wenn Sie es auf diese Weise schreiben

let gameStateMap: Map<GameState, Phaser.State> = new Map(...) 

Compiler zunächst einen Typ für new Map zu schließen versucht, dann überprüft, ob sie mit der Art kompatibel ist erklärt für gameStateMap.

In Ihrem Fall, wenn Arrays mit Elementen unterschiedlicher Typen beteiligt sind, kann der Compiler den allgemeinen Typ für sie nicht ableiten und verwendet stattdessen Union-Typ (der beabsichtigte Typ für Map Argument ist anscheinend [GameState, Phaser.State][]).

Compiler ein wenig Hilfe bei diesem muss, können Sie es schaffen, durch explizite generische Argumente Map Konstruktor geben, und dann können Sie explizite Typdeklaration weglassen für 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()] 
]);