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);
  });