Câu trả lời:
Chỉnh sửa : Điều này đã được sửa trong các phiên bản TS mới nhất. Trích dẫn bình luận của @ Simon_Weaver về bài đăng của OP:
Lưu ý: điều này đã được sửa chữa (không chắc phiên bản TS chính xác nào). Tôi nhận được các lỗi này trong VS, như bạn mong đợi:
Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.
Bạn có thể sử dụng từ điển đã nhập bằng cách tách ví dụ của bạn trong khai báo và khởi tạo, như:
var persons: { [id: string] : IPerson; } = {};
persons["p1"] = { firstName: "F1", lastName: "L1" };
persons["p2"] = { firstName: "F2" }; // will result in an error
id
biểu tượng? Có vẻ như nó là không cần thiết.
id
ký hiệu, bạn có thể khai báo loại khóa của từ điển sẽ là gì. Với tuyên bố trên, bạn không thể làm như sau:persons[1] = { firstName: 'F1', lastName: 'L1' }
id
biểu tượng có thể được bất cứ tên nào thích và được thiết kế như vậy để làm cho nó dễ dàng hơn để đọc mã. ví dụ { [username: string] : IPerson; }
Để sử dụng đối tượng từ điển trong bản thảo, bạn có thể sử dụng giao diện như dưới đây:
interface Dictionary<T> {
[Key: string]: T;
}
và, sử dụng điều này cho loại tài sản lớp học của bạn.
export class SearchParameters {
SearchFor: Dictionary<string> = {};
}
để sử dụng và khởi tạo lớp này,
getUsers(): Observable<any> {
var searchParams = new SearchParameters();
searchParams.SearchFor['userId'] = '1';
searchParams.SearchFor['userName'] = 'xyz';
return this.http.post(searchParams, 'users/search')
.map(res => {
return res;
})
.catch(this.handleError.bind(this));
}
Tôi đồng ý với thomaux rằng lỗi kiểm tra loại khởi tạo là lỗi TypeScript. Tuy nhiên, tôi vẫn muốn tìm cách khai báo và khởi tạo Từ điển trong một câu lệnh với kiểm tra loại chính xác. Việc thực hiện này dài hơn, tuy nhiên nó bổ sung thêm chức năng như a containsKey(key: string)
và remove(key: string)
phương thức. Tôi nghi ngờ rằng điều này có thể được đơn giản hóa một khi thuốc generic có sẵn trong bản phát hành 0.9.
Đầu tiên chúng ta khai báo lớp Từ điển cơ sở và Giao diện. Giao diện được yêu cầu cho bộ chỉ mục vì các lớp không thể thực hiện chúng.
interface IDictionary {
add(key: string, value: any): void;
remove(key: string): void;
containsKey(key: string): bool;
keys(): string[];
values(): any[];
}
class Dictionary {
_keys: string[] = new string[];
_values: any[] = new any[];
constructor(init: { key: string; value: any; }[]) {
for (var x = 0; x < init.length; x++) {
this[init[x].key] = init[x].value;
this._keys.push(init[x].key);
this._values.push(init[x].value);
}
}
add(key: string, value: any) {
this[key] = value;
this._keys.push(key);
this._values.push(value);
}
remove(key: string) {
var index = this._keys.indexOf(key, 0);
this._keys.splice(index, 1);
this._values.splice(index, 1);
delete this[key];
}
keys(): string[] {
return this._keys;
}
values(): any[] {
return this._values;
}
containsKey(key: string) {
if (typeof this[key] === "undefined") {
return false;
}
return true;
}
toLookup(): IDictionary {
return this;
}
}
Bây giờ chúng tôi khai báo loại cụ thể của người và giao diện Từ điển / Từ điển. Trong ghi chú PersonDixi cách chúng tôi ghi đè values()
và toLookup()
trả về các loại chính xác.
interface IPerson {
firstName: string;
lastName: string;
}
interface IPersonDictionary extends IDictionary {
[index: string]: IPerson;
values(): IPerson[];
}
class PersonDictionary extends Dictionary {
constructor(init: { key: string; value: IPerson; }[]) {
super(init);
}
values(): IPerson[]{
return this._values;
}
toLookup(): IPersonDictionary {
return this;
}
}
Và đây là một ví dụ khởi tạo và sử dụng đơn giản:
var persons = new PersonDictionary([
{ key: "p1", value: { firstName: "F1", lastName: "L2" } },
{ key: "p2", value: { firstName: "F2", lastName: "L2" } },
{ key: "p3", value: { firstName: "F3", lastName: "L3" } }
]).toLookup();
alert(persons["p1"].firstName + " " + persons["p1"].lastName);
// alert: F1 L2
persons.remove("p2");
if (!persons.containsKey("p2")) {
alert("Key no longer exists");
// alert: Key no longer exists
}
alert(persons.keys().join(", "));
// alert: p1, p3
containsKey(key: string): bool;
không hoạt động với TypeScript 1.5.0-beta . Nó nên được thay đổi thành containsKey(key: string): boolean;
.
Đây là một triển khai từ điển tổng quát hơn lấy cảm hứng từ điều này từ @dmck
interface IDictionary<T> {
add(key: string, value: T): void;
remove(key: string): void;
containsKey(key: string): boolean;
keys(): string[];
values(): T[];
}
class Dictionary<T> implements IDictionary<T> {
_keys: string[] = [];
_values: T[] = [];
constructor(init?: { key: string; value: T; }[]) {
if (init) {
for (var x = 0; x < init.length; x++) {
this[init[x].key] = init[x].value;
this._keys.push(init[x].key);
this._values.push(init[x].value);
}
}
}
add(key: string, value: T) {
this[key] = value;
this._keys.push(key);
this._values.push(value);
}
remove(key: string) {
var index = this._keys.indexOf(key, 0);
this._keys.splice(index, 1);
this._values.splice(index, 1);
delete this[key];
}
keys(): string[] {
return this._keys;
}
values(): T[] {
return this._values;
}
containsKey(key: string) {
if (typeof this[key] === "undefined") {
return false;
}
return true;
}
toLookup(): IDictionary<T> {
return this;
}
}
Nếu bạn muốn bỏ qua một thuộc tính, đánh dấu nó là tùy chọn bằng cách thêm một dấu hỏi:
interface IPerson {
firstName: string;
lastName?: string;
}
Bây giờ, có một thư viện cung cấp các bộ sưu tập có thể truy vấn, đánh máy mạnh trong bản thảo.
Những bộ sưu tập này là:
Thư viện được gọi là ts-generic-sưu tập-linq .
Mã nguồn trên GitHub:
https://github.com/VeritasSoftware/ts-generic-collections
NPM:
https://www.npmjs.com/package/ts-generic-collections-linq
Với thư viện này, bạn có thể tạo các bộ sưu tập (như List<T>
) và truy vấn chúng như hiển thị bên dưới.
let owners = new List<Owner>();
let owner = new Owner();
owner.id = 1;
owner.name = "John Doe";
owners.add(owner);
owner = new Owner();
owner.id = 2;
owner.name = "Jane Doe";
owners.add(owner);
let pets = new List<Pet>();
let pet = new Pet();
pet.ownerId = 2;
pet.name = "Sam";
pet.sex = Sex.M;
pets.add(pet);
pet = new Pet();
pet.ownerId = 1;
pet.name = "Jenny";
pet.sex = Sex.F;
pets.add(pet);
//query to get owners by the sex/gender of their pets
let ownersByPetSex = owners.join(pets, owner => owner.id, pet => pet.ownerId, (x, y) => new OwnerPet(x,y))
.groupBy(x => [x.pet.sex])
.select(x => new OwnersByPetSex(x.groups[0], x.list.select(x => x.owner)));
expect(ownersByPetSex.toArray().length === 2).toBeTruthy();
expect(ownersByPetSex.toArray()[0].sex == Sex.F).toBeTruthy();
expect(ownersByPetSex.toArray()[0].owners.length === 1).toBeTruthy();
expect(ownersByPetSex.toArray()[0].owners.toArray()[0].name == "John Doe").toBeTruthy();
expect(ownersByPetSex.toArray()[1].sex == Sex.M).toBeTruthy();
expect(ownersByPetSex.toArray()[1].owners.length == 1).toBeTruthy();
expect(ownersByPetSex.toArray()[1].owners.toArray()[0].name == "Jane Doe").toBeTruthy();
Index signatures are incompatible.
Type '{ firstName: string; }' is not assignable to type 'IPerson'.
Property 'lastName' is missing in type '{ firstName: string; }'.