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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13631557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 00:57:06  来源:igfitidea点击:

TypeScript Objects as Dictionary types as in C#

arraysobjectdictionarytypescript

提问by Robert Taylor

I have some JavaScript code that uses objects as dictionaries; for example a 'person' object will hold a some personal details keyed off the email address.

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

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

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

Is it possible to describe this in Typescript? or do I have to use an Array?

是否可以在 Typescript 中对此进行描述?还是我必须使用数组?

回答by Ryan Cavanaugh

In newer versions of typescript you can use:

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

type Customers = Record<string, Customer>

In older versions you can use:

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

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

You can also make an interface if you don't want to type that whole type annotation out every time:

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

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

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

回答by John Weisz

In addition to using an map-likeobject, there has been an actual Mapobjectfor some time now, which is available in TypeScript when compiling to ES6, or when using a polyfill with the ES6 type-definitions:

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

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

It supports the same functionality as Object, and more, with a slightly different syntax:

它支持与 相同的功能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");

This alone has several advantages over using a map-likeobject, such as:

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

  • Support for non-string based keys, e.g. numbers or objects, neither of which are supported by Object(no, Objectdoes not support numbers, it converts them to strings)
  • Less room for errors when not using --noImplicitAny, as a Mapalways has a keytype and a valuetype, whereas an object mightnot have an index-signature
  • The functionality of adding/removing items (key-value pairs) is optimized for the task, unlike creating properties on an Object
  • 支持非基于字符串的键,例如数字或对象,两者都不支持Object(不,Object不支持数字,它将它们转换为字符串)
  • 不使用时出错的余地较小--noImplicitAny,因为 aMap始终具有类型和类型,而对象可能没有索引签名
  • 添加/删除项目(键值对)的功能针对任务进行了优化,不像在Object

Additionally, a Mapobject provides a more powerful and elegant API for common tasks, most of which are not available through simple Objects without hacking together helper functions (although some of these require a full ES6 iterator/iterable polyfill for ES5 targets or below):

此外,Map对象为常见任务提供了更强大、更优雅的 API,其中大部分都不能通过简单的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());

回答by Dimitar Mazhlekov

You can use templated interfaces like this:

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

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

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

回答by Twen

You can also use the Record type in typescript :

您还可以在打字稿中使用 Record 类型:

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

回答by phil

Lodash has a simple Dictionary implementation and has good TypeScript support

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

Install Lodash:

安装 Lodash:

npm install lodash @types/lodash --save

Import and usage:

导入和使用:

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

回答by Nick N.

You can use Recordfor this:

您可以Record为此使用:

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

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

Example (A mapping between AppointmentStatus enum and some meta data):

示例(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' }
  }

Now with interface as value:

现在以接口作为值:

interface Icon { Name: string Color: string }

interface Icon { Name: string Color: string }

Usage:

用法:

const icon: SemanticIcon = iconMapping[appointment.Status]

const icon: SemanticIcon = iconMapping[appointment.Status]

回答by John

There is a library which provides strongly-typed, queryable collectionsin typescript.

有一个库在打字稿中提供强类型、可查询的集合

The collections are:

集合是:

  • List
  • Dictionary
  • 列表
  • 字典

The library is called ts-generic-collections. (Source code on GitHub)

该库名为ts-generic-collections。(GitHub 上的源代码

You can create a dictionary and query it like below:

您可以创建一个字典并像下面这样查询它:

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