Как определить число-> строковый словарь в Typescript?

Я играю с Typescript и конвертирую через небольшую библиотеку к нему из Javascript. В одной области кода было установлено статически определенное сопоставление имени дружественного ключа с их ключевым кодом. Исходный код выглядел так:

keys: { "Backspace": 8, "Tab": 9, "Enter": 13, ....etc.. };

Я определил это в Typescript через:

static keys: { [name: string]: number; } = { "Backspace": 8, "Tab": 9, "Enter": 13, ... etc.. };

Это работает нормально, однако в другой части кода используется противоположное отображение:

    chars: {8:"Backspace",9:"Tab",13:"Enter", ...etc... };

Итак, я попытался сделать тот же тип определения в Typescript, что я сделал ранее:

chars: { [code: number]: string; } = { 8: "Backspace", 9: "Tab", 13: "Enter", ...etc.. };

Не удается выполнить компиляцию со следующей ошибкой:

Невозможно преобразовать '{0: string; 1: строка; 2: строка; 4: строка; 8: строка; 9: строка;: string; } 'to' {[имя: номер]: строка; } ': Индексные подписи типов' {0: string; 1: строка; 2: строка; 4: строка; 8: строка; 9: строка;: string; } 'и' {[имя: номер]: строка; } 'несовместимы

Как определить это сопоставление в Typescript?

Ответ 1

Проблема заключается в том, что в JavaScript - и, следовательно, в TypeScript - ключи объектного литерала всегда являются строками и поэтому не могут быть назначены переменной с индексом числа.

Объект с индексом числа - это массив - и поэтому вы должны это сделать:

var chars: string[] = [];
chars[8]= "Backspace";
chars[9]= "Tab";
chars[13] = "Enter";

Ответ 2

Здесь находится библиотека под названием Classical.js *, которая может помочь вам выполнить эту и подобные проблемы. Он, в частности, определяет двуязычный словарь. Для вашего варианта использования код будет выглядеть так:

import c = Classical.Collections;

var keys = new c.Dictionary<string, number>();
keys.add("Backspace", 8);
keys.add("Tab", 9);
keys.add("Enter", 13);
//etc...

keys.getValue("Backspace"); //8
keys.getValue("Tab"); //9
keys.getValue("Enter"); //13
//etc...

Словарь < TKey, TValue > работает со всеми типами объектов и не имеет проблем с конфликтами имен, такими как ключи с именем "конструктор".

Для противоположного отображения вы можете либо построить инверсный словарь, либо запросить текущий так:

keys.query().single(pair => pair.key === 8).value; //"Backspace"
keys.query().single(pair => pair.key === 9).value; //"Tab"
keys.query().single(pair => pair.key === 13).value; //"Enter"
//etc...

Если вы хотите попробовать, посетите Classical, откройте папку bin и добавьте classic.js и classic.d.ts в ваш проект.

Надеюсь, что это поможет.


* Я один из разработчиков классической команды

Ответ 3

Действительно, js внутренне содержит только индексы на основе строк (при этом Array отличается от {}), но преобразование строк и чисел является устойчивым в js:

var x = {0 : "asdf",1:"bb"} 
alert(x[0])
alert(x[1])

Я думаю, что typescript также должен поддерживать его и создать рабочий элемент, на который вы можете проголосовать: http://typescript.codeplex.com/workitem/832