TypeScript对象与c#中的字典类型一样

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

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


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

是否有可能在Typescript中描述这一点?或者我必须使用数组?

331760 次浏览

在较新的typescript版本中,您可以使用:

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

你可以像这样使用模板化接口:

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


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

除了使用map-就像对象外,实际的Map对象已经存在一段时间了,它在编译到ES6的TypeScript中可用,或者在使用带有ES6 类型定义的polyfill时可用:

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

这本身就比使用map-就像对象有几个优点,例如:

  • 支持非基于字符串的键,例如数字或对象,这两者都不受Object的支持(不,Object不支持数字,它将它们转换为字符串)
  • 当不使用--noImplicitAny时,出错的空间更小,因为Map总是有关键类型和价值类型,而对象可能没有索引签名
  • 添加/删除项(键值对)的功能针对不同于在Object上创建属性任务进行了优化

此外,Map对象为常见任务提供了更强大、更优雅的API,其中大多数任务在不组合helper函数的情况下无法通过简单的__abc1获得(尽管其中一些任务对于ES5或以下目标需要完整的ES6迭代器/可迭代填充):

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

Lodash有一个简单的Dictionary实现,并有良好的TypeScript支持

安装Lodash:

npm install lodash @types/lodash --save

进口及使用:

import { Dictionary } from "lodash";
let properties : Dictionary<string> = {
"key": "value"
}
console.log(properties["key"])

你也可以在typescript中使用Record类型:

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

你可以使用Record来实现:

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

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

  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为值:

interface图标{ 名称:字符串 颜色:字符串 代码}< / > < / p >

用法:

const icon: SemanticIcon = iconMapping[appointment.Status]