TypeScript Objects เป็นพจนานุกรมประเภทเช่นเดียวกับใน C #


336

ฉันมีรหัสจาวาสคริปต์ที่ใช้วัตถุเป็นพจนานุกรม ตัวอย่างเช่นวัตถุ 'person' จะเก็บรายละเอียดส่วนตัวบางอย่างที่อยู่อีเมล

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

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

เป็นไปได้ไหมที่จะอธิบายเรื่องนี้ใน typescript หรือฉันต้องใช้อาร์เรย์?


5
โพสต์เก่า แต่ทราบว่ามีแผนที่ ES6
Old Badman Gray

คำตอบ:


547

ใน 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

2
นั่นเป็นวิธีที่มีประโยชน์เพื่อให้แน่ใจว่าคอมไพเลอร์ จำกัด ดัชนีไว้ที่สตริง น่าสนใจ ดูเหมือนคุณจะไม่สามารถระบุประเภทดัชนีให้เป็นอย่างอื่นนอกจากสตริงหรือเลขจำนวนเต็มได้ แต่ก็เหมาะสมแล้วเนื่องจากมันจะจับคู่กับดัชนีวัตถุ JS ดั้งเดิม
Ken Smith

5
คุณอาจจะรู้สิ่งนี้ แต่ก็มีวิธีการที่น่าสนใจเช่นกันวิธีการใหญ่ที่ไม่มีวิธีที่ปลอดภัยและง่ายในการย้ำผ่านสมาชิกทั้งหมด ตัวอย่างเช่นรหัสนี้แสดงให้เห็นว่าmapมีสมาชิกสองคน: (<any> Object.prototype) .something = function () {}; แผนที่ชั้นลูกค้า {} var: {[email: string]: ลูกค้า; } = {}; map ['foo@gmail.com '] = ลูกค้าใหม่ (); สำหรับ (var i ในแผนที่) {console.log (แผนที่ [i])}
Ken Smith

5
คุณจะลบออกจากมันได้อย่างไร
TDaver

24
อีกวิธีที่น่าสนใจคืออินเตอร์เฟส MapStringTo <T> {[key: string]: T; } และประกาศตัวแปรเช่นvar map:MapStringTo<Customer> = {};
orellabac

1
รับทราบว่าข้อ จำกัด ของดัชนีไม่ทำงานอีกต่อไป อ่านเพิ่มเติม.
David Sherret

127

นอกเหนือจากการใช้วัตถุคล้ายแผนที่แล้วยังมีMapวัตถุจริงอยู่พักหนึ่งซึ่งสามารถใช้งานได้ใน TypeScript เมื่อรวบรวมเป็น ES6 หรือเมื่อใช้ polyfill กับคำจำกัดความประเภท ES6 :

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เนื่องจาก a Mapมักจะมีประเภทของคีย์และชนิดของค่าในขณะที่วัตถุอาจไม่มีลายเซ็นของดัชนี
  • ฟังก์ชันการทำงานของการเพิ่ม / ลบรายการ (คู่คีย์ - ค่า) ถูกปรับให้เหมาะกับงานซึ่งแตกต่างจากการสร้างคุณสมบัติบนObject

นอกจากนี้Mapวัตถุยังมี API ที่ทรงพลังและสง่างามสำหรับงานทั่วไปซึ่งส่วนใหญ่ไม่สามารถใช้งานได้โดยง่ายObjectโดยไม่ต้องแฮ็คฟังก์ชั่นตัวช่วย (แม้ว่าบางอย่างต้องใช้ ES6 iterator / iterable 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());

2
ที่น่ากลัว! แต่น่าเสียดายที่การใช้ซีเรียลJSON.stringify()ไลเซชั่นผิดดังนั้นจึงสามารถใช้งานได้เช่นสำหรับ socket.io :(
Lion

@Lion - ใช่แล้วการMapทำให้เป็นอนุกรมนั้นค่อนข้างตลก I สำหรับหนึ่งให้ทำการแปลงเป็นคู่ของคีย์ - ค่า - คู่ก่อนที่จะทำให้เป็นอันดับแล้วกลับมา (เช่นออบเจ็กต์ของ{ key: "John", value: { firstName: "John" } })
John Weisz

2
ฉันทำผิดพลาดจากการใช้แผนที่แทนที่จะเป็นวัตถุเก่าแบบธรรมดาและการทำให้เป็นอันดับฉันจริงๆ คัดท้ายชัดเจนในความคิดของฉัน
378380

1
นี่คือสิ่งที่สวยงาม ดีใจที่คุณเป็นแรงบันดาลใจให้ฉันจุ่มลงในแผนที่ สิ่งนี้จะแทนที่โครงสร้างคีย์แมป / พจนานุกรมปกติของฉันเพราะมันง่ายกว่ามากในการพิมพ์คีย์อย่างยิ่ง
Methodician

77

คุณสามารถใช้ส่วนต่อประสาน templated ดังนี้:

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

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

7
โปรดทราบว่าสิ่งนี้ขัดแย้งกับประเภทแผนที่ es6 ดีกว่าคำตอบอื่น ๆ เพราะข้อ จำกัด ดัชนีจะถูกละเว้น
Badman เก่า Gray

ฉันจะตรวจสอบว่ามีคีย์อยู่ในพจนานุกรมได้อย่างไร
samneric

dict.hasOwnProperty ('สำคัญ')
Dimitar Mazhlekov

1
ผมใช้พจนานุกรมแทนแผนที่ไปสู่ความสับสนหลีกเลี่ยงและคุณสามารถใช้สัญกรณ์วัตถุตัวอักษร:let dict: Dictionary<number> = { "one": 1, "two": 2 };
PhiLho

8

คุณยังสามารถใช้ประเภทระเบียนใน typescript:

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

5

Lodash มีการนำพจนานุกรมมาใช้อย่างง่ายและสนับสนุน TypeScript ที่ดี

ติดตั้ง Lodash:

npm install lodash @types/lodash --save

นำเข้าและการใช้งาน:

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

3

คุณสามารถใช้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 Icon { Name: string Color: string }

การใช้งาน:

const icon: SemanticIcon = iconMapping[appointment.Status]


มันมีประโยชน์มาก คุณจะใช้สตริงenumหรือclass/objectสำหรับAppointmentStatus- หรือมันเป็นเรื่องสำคัญ?
Drenai

@Drenai ไม่สำคัญมันเป็นสิ่งที่คุณต้องการ
Nick N.

-2

มีห้องสมุดที่ให้คอลเลกชันที่พิมพ์ได้อย่างน่าสงสัยใน typescript

คอลเลกชันคือ:

  • รายการ
  • พจนานุกรม

ห้องสมุดที่เรียกว่าTS-ทั่วไปคอลเลกชัน ( ซอร์สโค้ดบน GitHub )

คุณสามารถสร้างพจนานุกรมและสืบค้นตามด้านล่าง:

  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);
  });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.