385

我有一些使用对象作为字典的 JavaScript 代码;例如,“人”对象将保存一些与电子邮件地址相关的个人详细信息。

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

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

是否可以在 Typescript 中描述这一点?还是我必须使用数组?

4

6 回答 6

607

在较新版本的打字稿中,您可以使用:

type Customers = Record<string, Customer>

在旧版本中,您可以使用:

var map: { [email: string]: Customer; } = { };
map['foo@gmail.com'] = new Customer(); // OK
map[14] = new Customer(); // Not OK, 14 is not a string
map['bar@hotmail.com'] = 'x'; // Not OK, 'x' is not a customer

如果您不想每次都输入整个类型注释,您也可以创建一个接口:

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

var map: StringToCustomerMap = { };
// Equivalent to first line of above
于 2012-11-29T17:51:40.263 回答
149

除了使用类似map 的对象外,现在还有一个实际的Map对象,当编译到 ES6 或使用带有 ES6类型定义的 polyfill 时,它在 TypeScript 中可用:

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(不,Object不支持数字,它将它们转换为字符串)
  • 不使用时出错的空间更小--noImplicitAny,因为 aMap始终具有类型和类型,而对象可能没有索引签名
  • 添加/删除项目(键值对)的功能针对任务进行了优化,这与在Object

此外,一个Map对象为常见任务提供了一个更强大和优雅的 API,其中大部分在 simple Objects 中无法使用,而无需将辅助函数组合在一起(尽管其中一些需要完整的 ES6 迭代器/可迭代的 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());
于 2017-02-14T10:36:14.767 回答
83

您可以使用这样的模板化接口:

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

let dict: Map<number> = {};
dict["one"] = 1;
于 2015-09-26T14:59:33.533 回答
11

您还可以在 typescript 中使用 Record 类型:

export interface nameInterface { 
    propName : Record<string, otherComplexInterface> 
}
于 2018-03-26T15:18:22.313 回答
9

您可以Record为此使用:

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

示例(AppointmentStatus 枚举和一些元数据之间的映射):

  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]

于 2019-09-30T14:02:34.263 回答
8

Lodash 有一个简单的 Dictionary 实现并且有很好的 TypeScript 支持

安装 Lodash:

npm install lodash @types/lodash --save

导入和使用:

import { Dictionary } from "lodash";
let properties : Dictionary<string> = {
    "key": "value"        
}
console.log(properties["key"])
于 2017-10-25T17:20:28.053 回答