2016-05-03 15 views
8

Chcę MyInterface.dic być jak słownika name: value, zdefiniować go w następujący sposób:Typescript: Index podpis brakuje w rodzaju

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

Teraz utworzyć funkcję, która czeka na mój typ:

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

i wejście:

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

Czekam foo(o) za prawidłowe, ale kompilator spada:

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

wiem, że jest to możliwe odlewanie: let o: MyInterface = { ... } które rade ale pytanie brzmi, dlaczegomaszynopis nie rozpoznaje typ?


Extra: działa dobrze jeśli o jest zadeklarowana inline:

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

Odpowiedz

9

Problem polega na tym, że kiedy typ jest wywnioskować, następnie typ o jest:

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

To nie taki sam jak { dic: { [name: string]: number } }. Krytycznie, z najwyższym podpisem nie możesz zrobić czegoś takiego jak o.dic['x'] = 1. Z drugim podpisem jesteś.

Są to równoważne typy w czasie wykonywania (w rzeczywistości są to dokładnie takie same wartości), ale duża część bezpieczeństwa TypeScript wynika z faktu, że nie są one takie same, i że pozwolą ci tylko leczyć obiekt jako słownik, jeśli wie, że jest wyraźnie przeznaczony jako jeden. To właśnie powoduje, że przypadkowo nie czytasz i piszesz całkowicie nieistniejących właściwości obiektów.

Rozwiązaniem jest zapewnienie maszynopis wie, że jest on przeznaczony jako słownika. Oznacza to, że:

  • Jawnie zapewniając typ gdzieś, że mówi to jest to słownik:

    let o: MyInterface

  • Stwierdzenie, że jest słownikiem inline:

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

  • Zapewnienie, że jest to początkowy typ, który TypeScript oferuje:

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

Jeśli jest to przypadek, gdzie maszynopis uważa, że ​​to normalny przedmiot z zaledwie dwóch właściwości, a następnie spróbuj go użyć później jak słownik, będzie nieszczęśliwy.

+0

> Z drugim podpisem jesteś. W rzeczywistości Moje IDE nie pozwala mi na wykonywanie 'o.dic.x' – Manu

+1

Dobrze, przepraszam, to powinna być składnia indeksu ('o.dic ['x'] = 1'). Przykład zaktualizowany. –

+2

Aktualizacja! TypeScript 2 powinien teraz automatycznie wykonać tę konwersję, jeśli jest ona ważna: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#implicit-index-signatures –