2016-05-03 18 views
8

voglio MyInterface.dic essere come un dizionario name: value, definisco come segue:tipografico: firma Indice manca nel tipo di

interface MyInterface { 
    dic: { [name: string]: number } 
} 

Ora creare una funzione che attende per il mio tipo:

function foo(a: MyInterface) { 
    ... 
} 

e l'ingresso:

let o = { 
    dic: { 
     'a': 3, 
     'b': 5 
    } 
} 

mi aspetto foo(o) di essere corretto, ma il compilatore è in calo:

foo(o) // Typescript error: Index signature is missing in type { 'a': number, 'b': number } 

So che c'è una possibile fusione: let o: MyInterface = { ... } che fare il trucco, ma la domanda è: perché dattiloscritto non riconosce il mio tipo?


Extra: funziona bene se o è dichiarata in linea:

foo({ 
    dic: { 
    'a': 3, 
    'b': 5 
    } 
}) 

risposta

9

Il problema è che quando il tipo è dedotto, quindi il tipo di o è:

{ dic: { a: number, b: number } } 

Questo non è lo stesso di { dic: { [name: string]: number } }. In modo critico, con la firma in alto non ti è permesso fare qualcosa come o.dic['x'] = 1. Con la seconda firma sei.

Sono tipi equivalenti in fase di esecuzione (in effetti, sono esattamente lo stesso valore), ma una parte importante della sicurezza di TypeScript deriva dal fatto che non sono gli stessi e che ti consente solo di trattare un oggetto come dizionario se sa che è esplicitamente inteso come uno. Questo è ciò che ti impedisce di leggere e scrivere accidentalmente proprietà totalmente inesistenti sugli oggetti.

La soluzione è garantire che TypeScript sappia che è inteso come dizionario. Ciò significa:

  • fornendo esplicitamente un tipo da qualche parte che dice che si tratta di un dizionario:

    let o: MyInterface

  • affermando che fosse una linea dizionario:

    let o = { dic: <{ [name: string]: number }> { 'a': 1, 'b': 2 } }

  • Assicurandosi che sia il tipo iniziale che TypeScript dedica a te:

    foo({ dic: { 'a': 1, 'b': 2 } })

Se c'è un caso in cui dattiloscritto pensa che sia un oggetto normale con solo due proprietà, e quindi si tenta di utilizzare in un secondo momento come un dizionario, sarà infelice.

+0

> Con la seconda firma sei. In realtà il mio IDE non mi permette di fare 'o.dic.x' – Manu

+1

Buona cattura, mi dispiace, avrebbe dovuto essere la sintassi dell'indice ('o.dic ['x'] = 1'). Esempio aggiornato. Aggiornamento –

+2

! TypeScript 2 ora dovrebbe eseguire automaticamente questa conversione per te, se è valida: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#implicit-index-signatures –

Problemi correlati