TypeScript对象作为C#中的字典类型

Rob*_*lor 316 arrays dictionary object typescript

我有一些JavaScript代码使用对象作为字典; 例如,"人"对象将保留一些键入电子邮件地址的个人详细信息.

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

adding   > "people[<email>] = <data>;" 
getting  > "var data = people[<email>];" 
deleting > "delete people[<email>];"
Run Code Online (Sandbox Code Playgroud)

是否有可能在Typescript中描述这个?还是我必须使用数组?

Rya*_*ugh 513

当然:

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
Run Code Online (Sandbox Code Playgroud)

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

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

var map: StringToCustomerMap = { };
// Equivalent to first line of above
Run Code Online (Sandbox Code Playgroud)

  • 另一个有趣的方法是:接口MapStringTo <T> {[key:string]:T; 并声明变量,如`var map:MapStringTo <Customer> = {};` (24认同)
  • 你可能知道这一点,但是这种方法也存在一些潜在的问题,最重要的是没有安全简便的方法来遍历所有成员.例如,这段代码显示`map`包含两个成员:(<any> Object.prototype).something = function(){}; class Customer {} var map:{[email:string]:Customer; } = {}; map ['foo@gmail.com'] = new Customer(); for(var i in map){console.log(map [i])} (5认同)
  • 你怎么从中删除? (5认同)
  • 这是确保编译器将索引限制为字符串的有用方法.有趣.看起来你不能将索引类型指定为除字符串或整数之外的任何东西,但这是有道理的,因为它只是映射到本机JS对象索引. (2认同)

Joh*_*isz 114

除了使用类似地图的对象之外,还有一段时间的实际Map对象,在编译为ES6时,或者在使用带有ES6 类型定义的polyfill时,可以在TypeScript中使用:

let people = new Map<string, Person>();
Run Code Online (Sandbox Code Playgroud)

它支持相同的功能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");
Run Code Online (Sandbox Code Playgroud)

仅使用这一点与使用类似地图的对象相比有几个优点,例如:

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

此外,一个Map对象为常见任务提供了一个更强大和更优雅的API,其中大部分都不能通过简单Object的方式获得而不会将帮助函数混合在一起(尽管其中一些需要ES5目标或以下的完整ES6迭代器/可迭代polyfill):

// 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());
Run Code Online (Sandbox Code Playgroud)

  • 我犯了使用地图而不是普通旧对象的错误,而序列化确实让我着迷。在我看来,避开。 (4认同)
  • 棒极了!但遗憾的是它使用`JSON.stringify()` 序列化错误,因此它可以用于例如socket.io :( (2认同)

小智 76

您可以使用如下模板化界面:

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

let dict: Map<number> = {};
dict["one"] = 1;
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这与es6 Map类型冲突.比其他答案更好,因为忽略了索引约束. (7认同)
  • 我使用 Dictionary 而不是 Map 来避免混淆,您可以使用文字对象表示法:`let dict: Dictionary&lt;number&gt; = { "one": 1, "two": 2 };` (2认同)

Twe*_*wen 8

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

export interface nameInterface { 
    propName : Record<string, otherComplexInterface> 
}
Run Code Online (Sandbox Code Playgroud)


Nic*_* N. 7

您可以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' }
  }
Run Code Online (Sandbox Code Playgroud)

现在以接口作为值:

interface Icon { Name: string Color: string }

用法:

const icon: SemanticIcon = iconMapping[appointment.Status]


phi*_*hil 5

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

安装Lodash:

npm install lodash @types/lodash --save
Run Code Online (Sandbox Code Playgroud)

进口和使用:

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