TypeScript Объекты как типы словарей, как в С#
У меня есть некоторый код JavaScript, который использует объекты в качестве словарей; например, объект person будет содержать некоторые личные данные, введенные в адрес электронной почты.
var people = {<email> : <'some personal data'>};
adding > "people[<email>] = <data>;"
getting > "var data = people[<email>];"
deleting > "delete people[<email>];"
Можно ли описать это в Typescript? или я должен использовать массив?
Ответы
Ответ 1
В новых версиях машинописи вы можете использовать Record<string, Customer>
В старых версиях вы можете использовать:
var map: { [email: string]: Customer; } = { };
map['[email protected]'] = new Customer(); // OK
map[14] = new Customer(); // Not OK, 14 is not a string
map['[email protected]'] = 'x'; // Not OK, 'x' is not a customer
Вы также можете создать интерфейс, если не хотите каждый раз печатать аннотацию всего типа:
interface StringToCustomerMap {
[email: string]: Customer;
}
var map: StringToCustomerMap = { };
// Equivalent to first line of above
Ответ 2
В дополнение к использованию объекта, подобного карте, в течение некоторого времени был фактический Map
object, который доступен в TypeScript при компиляции на ES6 или при использовании polyfill с ES6 определения типов:
let people = new Map<string, Person>();
Он поддерживает те же функции, что и Object
, и многое другое, с немного отличающимся синтаксисом:
// Adding an item (a key-value pair):
people.set("John", { firstName: "John", lastName: "Doe" });
// Checking for the presence of a key:
people.has("John"); // true
// Retrieving a value by a key:
people.get("John").lastName; // "Doe"
// Deleting an item by a key:
people.delete("John");
Это само по себе имеет несколько преимуществ перед использованием объекта, подобного карте, например:
- Поддержка нестрочных ключей, например. номера или объекты, ни один из которых не поддерживается
Object
(no, Object
не поддерживает числа, преобразует их в строки)
- Меньше места для ошибок при использовании
--noImplicitAny
, так как Map
всегда имеет тип ключа и тип значения, тогда как у объекта может отсутствовать подпись-подпись
- Функциональность добавления/удаления элементов (пары ключ-значение) оптимизирована для задачи, в отличие от создания свойств на
Object
Кроме того, объект Map
предоставляет более мощный и элегантный API для обычных задач, большинство из которых недоступны с помощью простого Object
без взлома вспомогательных функций (хотя для некоторых из них требуется полный итератор ES6/iterable polyfill для целей ES5 или ниже):
// Iterate over Map entries:
people.forEach((person, key) => ...);
// Clear the Map:
people.clear();
// Get Map size:
people.size;
// Extract keys into array (in insertion order):
let keys = Array.from(people.keys());
// Extract values into array (in insertion order):
let values = Array.from(people.values());
Ответ 3
Вы можете использовать шаблонные интерфейсы, например:
interface Map<T> {
[K: string]: T;
}
let dict: Map<number> = {};
dict["one"] = 1;
Ответ 4
Вы также можете использовать тип записи в машинописном тексте:
export interface nameInterface {
propName : Record<string, otherComplexInterface>
}
Ответ 5
Lodash имеет простую реализацию словаря и имеет хорошую поддержку TypeScript
Установите Lodash:
npm install lodash @types/lodash --save
Импорт и использование:
import { Dictionary } from "lodash";
let properties : Dictionary<string> = {
"key": "value"
}
console.log(properties["key"])
Ответ 6
Вы можете использовать Record
для этого:
https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt
Пример:
const iconMapping: Record<AppointmentStatus, Icon> = {
[AppointmentStatus.Failed]: { Name: 'calendar times', Color: 'red' },
[AppointmentStatus.Canceled]: { Name: 'calendar times outline', Color: 'red' },
[AppointmentStatus.Confirmed]: { Name: 'calendar check outline', Color: 'green' },
[AppointmentStatus.Requested]: { Name: 'calendar alternate outline', Color: 'orange' },
[AppointmentStatus.None]: { Name: 'calendar outline', Color: 'blue' }
}
Теперь с интерфейсом в качестве значения:
interface Icon {
Name: string
Color: string
}
Использование:
const icon: SemanticIcon = iconMapping[appointment.Status]
Ответ 7
Существует библиотека, которая предоставляет строго типизированные, запрашиваемые коллекции в машинописи.
Коллекции:
Библиотека называется ts-generic-collection. (Исходный код на GitHub)
Вы можете создать словарь и запросить его, как показано ниже:
it('firstOrDefault', () => {
let dictionary = new Dictionary<Car, IList<Feature>>();
let car = new Car(1, "Mercedez", "S 400", Country.Germany);
let car2 = new Car(2, "Mercedez", "S 500", Country.Germany);
let features = new List<Feature>();
let feature = new Feature(1, "2 - Door Sedan");
features.add(feature);
dictionary.add(car, features);
features = new List<Feature>();
feature = new Feature(2, "4 - Door Sedan");
features.add(feature);
dictionary.add(car2, features);
//query
let first = dictionary.firstOrDefault(x => x.key.name == "Mercedez");
expect(first.key.id = 1);
});