polia - TypeScript objekty ako typy slovníkov ako v C#


Mám nejaký kód v JavaScripte, ktorý používa objekty ako slovníky; napríklad objekt 'osoba' bude obsahovať niektoré osobné údaje uložené pod e-mailovou adresou.

var people = {<email> : <'some personal data'>};

adding   > "people[<email>] = <data>;" 
getting  > "var data = people[<email>];" 
deleting > "delete people[<email>];"

Je možné to popísať v TypeScript? Alebo musím použiť pole?

Odpoveď č. 1

V novších verziách TypeScriptu môžete použiť:

type Customers = Record<string, Customer>

V starších verziách môžete použiť:

var map: { [email: string]: Customer; } = { };
map['[email '] = new Customer(); // OK
map[14] = new Customer(); // Not OK, 14 is not a string
map['[email '] = 'x'; // Not OK, 'x' is not a customer

Môžete si tiež vytvoriť rozhranie, ak nechcete zakaždým zadávať celý ten typový zápis:

interface StringToCustomerMap {
    [email: string]: Customer;
}

var map: StringToCustomerMap = { };
// Equivalent to first line of above

Odpoveď č. 2

Okrem používania objektu podobného mape existuje už niekoľko rokov aj skutočný objekt Map, ktorý je k dispozícii v TypeScripte pri kompilácii do ES6 alebo pri použití polyfillu s definíciami typov ES6:

let people = new Map<string, Person>();

Podporuje rovnakú funkcionalitu ako Object a viac, s mierne odlišnou syntaxou:

// 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");

To samo o sebe má niekoľko výhod oproti použitiu objektu podobného mape, ako napríklad:

  • Podpora pre kľúče, ktoré nie sú reťazcové, napr. čísla alebo objekty, ktoré Object nepodporuje (nie, Object nepodporuje čísla, tie prevádza na reťazce)
  • Menej priestoru pre chyby pri nepoužívaní --noImplicitAny, pretože Map vždy má typ key a typ value, zatiaľ čo objekt nemusí mať indexový podpis
  • Funkcionalita pridávania/odoberania položiek (pári kľúč-hodnota) je optimalizovaná pre túto úlohu, na rozdiel od vytvárania vlastností na Object

Okrem toho objekt Map poskytuje výkonnejšie a elegantnejšie API pre bežné úlohy, z ktorých väčšina nie je dostupná prostredníctvom jednoduchých Object-ov bez pospájania pomocných funkcií (hoci niektoré z nich vyžadujú plnú polyfill ES6 iterátora/iterable pre ciele ES5 alebo nižšie):

// 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());

Odpoveď č. 3

Môžete použiť šablónové rozhrania takto:

interface Map<T> {
    [K: string]: T;
}

let dict: Map<number> = {};
dict["one"] = 1;

Odpoveď č. 4

Na toto môžete použiť Record:

https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt

Príklad (Mapovanie medzi enum AppointmentStatus a niektorými metaúdajmi):

  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' }
  }

Teraz s rozhraním ako hodnotou:

interface Icon { Name: string Farba: string }

Použitie :

const icon: SemanticIcon = iconMapping[appointment.Status]

Odpoveď č. 5

Môžete tiež použiť typ Record v TypeScripte:

export interface nameInterface { 
    propName : Record<string, otherComplexInterface> 
}

Súvisiace články