2016-05-16 20 views
10

dati un oggetto sito web creato in questo modocome dichiarare una mappa contenente alcuni oggetti con flowtype & immutable.js

import {Map} from 'immutable' 
const website = new Map({name: 'My Website', url: 'http://www.myw.fr'}) 

Come avrei potuto dichiarare una websiteType che sarebbe una mappa che contiene esattamente le proprietà date. So che posso fare:

declare type websiteType = Map<string,string> 

Ma mi piacerebbe essere più specifici, e dichiarare una mappa che deve contenere le proprietà name e url di tipo string.

È possibile?

+0

Ehi, in realtà sto cercando una risposta simile. Hai trovato qualcosa? –

+1

Ciao Non ho trovato un modo per farlo con flowtype. Tuttavia, vi è il tipo di record in immutablejs che consente di raggiungere lo stesso obiettivo dichiarando una mappa vincolata con valori predefiniti. Cf: https://facebook.github.io/immutable-js/docs/#/Record – Nihau

risposta

1

Speriamo di avere ragione, perché non ho mai usato una mappa da "immutabile", quindi userò uno es6 Map.

Perché non usi solo una lezione?

class Website extends Map<string, string> { 
    constructor(name: string, url: string) { 
     super() 
     this.set("name", name) 
     this.set("url", url) 
    } 
} 

In questo modo è possibile inizializzare in questo modo:

const website = new Website("awesome", "www.awesome.com") 

e quindi eseguire le operazioni get e set.

Se si dimentica che i parametri flowtype generano un errore.

Spero che questa sia una soluzione per voi.

EDIT:

Si potrebbe anche solo creare una funzione che inizializza la vostra mappa.

declare type WebsiteType = Map<string, string> 

function createWebsite(name: string, description: string) { 
    const website: WebsiteType = new Map 
    website.set("name", name) 
    website.set("description", description) 
    return website 
} 

Tuttavia trovo la prima soluzione più bello perché ti dà un tipo di sito web e non c'è bisogno di creare una funzione di creatore.

EDIT:

Se si desidera che la stessa sintassi come facevi la mappa di inizializzazione, si potrebbe anche fare:

class Website extends Map<string, string> { 
    constructor({name, url, ...rest}) { 
     super() 
     this.set("name", name) 
     this.set("url", url) 
     for(const name in rest) { 
      this.set(name, rest[name]) 
     } 
    } 
} 

Tuttavia penso che il primo significativo.

-2

Immutable Map supporta getter/setter, quindi è possibile trattarlo esattamente come un oggetto JS normale. Basta creare un tipo con i campi che è necessario vincolare:

type Website = { 
    name: string, 
    url: string, 
} 

quindi utilizzarlo ovunque è necessario:

import {Map} from 'immutable' 

const website: Website = new Map({ 
    name: 'My Website', 
    url: 'http://www.myw.fr' 
}) 

website.name; // No error 
website.url; // No error 
website.somethingElse; // Error 
+1

Non credo che l'instancabile supporto per la mappa diretta avvenga/imposta, devi usare i metodi .get/.set su di essi. Ma so che i Records immutabili fanno, quindi proverò domani al lavoro, sarebbe bello se funzionasse :) tornerà a validare la risposta se è così. thx u – Nihau

+1

Ho provato questo. Ricevo errori di dattiloscritto. Anche se il dattiloscritto lo permettesse, ci sarebbero ancora errori di runtime per il motivo menzionato da Nihau (deve usare i metodi .get/.set). – Brian

0

Non credo Map è la soluzione a questo problema. Puoi restringerlo usando enumerazioni ma questo non sembra risolvere il problema.Ecco alcuni risultati che ho ottenuto mentre giocavo:

type MyKeys = 'A' | 'B'; 
declare type MyMapType = Map<MyKeys, number>; 

const TinyMap: MyMapType = Map({ 
    A: 1, 
}); 
// As expected this doesn't give an error 
console.log(TinyMap.get('B')); 

const MyMap: MyMapType = Map({ 
    A: 1, 
    B: 2, 
}); 

// Just a 'number' 
MyMap.get('A'); 

// Somewhat surprisingly this works fine 
const NewMap = MyMap.set('A', 'a'); 

// Now of type 'number | string' 
NewMap.get('A') 

// Forcing the return into the type causes the error that one 
// perhaps would expect: 'string This type is incompatible with number' 
const AnotherMap: MyMapType = MyMap.set('A', 'a');