Yanıtlar:
Düzenleme : Bu, en son TS sürümlerinde düzeltildi. @ Simon_Weaver'ın OP yayınına yaptığı yorumdan alıntı:
Not: Bu o zamandan beri düzeltildi (hangi kesin TS versiyonundan emin değilim). Beklediğiniz gibi VS bu hataları alıyorum:
Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.
Yazdığınız sözlüğü, beyan ve başlatma işleminde örneğinizi bölerek kullanabilirsiniz, örneğin:
var persons: { [id: string] : IPerson; } = {};
persons["p1"] = { firstName: "F1", lastName: "L1" };
persons["p2"] = { firstName: "F2" }; // will result in an error
id
sembole ihtiyacınız var ? Gereksiz gibi görünüyor.
id
sözlüğün anahtarlarının türünün ne olacağını bildirebilirsiniz. Yukarıdaki beyan ile aşağıdakileri yapamazsınız:persons[1] = { firstName: 'F1', lastName: 'L1' }
id
sembolü gibi bir şey seni adlandırılabilir ve daha kolay kod okunmasını sağlamak için bu şekilde tasarlanmıştır. ör. { [username: string] : IPerson; }
Daktiloda sözlük nesnesini kullanmak için arayüzü aşağıdaki gibi kullanabilirsiniz:
interface Dictionary<T> {
[Key: string]: T;
}
ve bunu sınıf özellik türünüz için kullanın.
export class SearchParameters {
SearchFor: Dictionary<string> = {};
}
bu sınıfı kullanmak ve başlatmak,
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));
}
Thomaux ile başlatma tipi kontrol hatasının bir TypeScript hatası olduğunu kabul ediyorum. Ancak, yine de doğru tür denetimi ile tek bir ifadede bir Sözlük bildirmek ve başlatmak için bir yol bulmak istedim. Bu uygulama daha uzundur, ancak a containsKey(key: string)
ve remove(key: string)
yöntem gibi ek işlevler ekler . 0.9 sürümünde jenerikler mevcut olduğunda bunun basitleştirilebileceğinden şüpheleniyorum.
İlk önce temel Sözlük sınıfını ve Arabirimini bildiririz. Sınıflar bunları uygulayamadığından, arabirim dizinleyici için gereklidir.
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;
}
}
Şimdi Kişiye özgü tür ve Sözlük / Sözlük arayüzünü ilan ediyoruz. PersonDictionary not nasıl geçersiz kılmak values()
ve toLookup()
doğru türleri döndürmek için.
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;
}
}
İşte basit bir başlatma ve kullanım örneği:
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;
, TypeScript 1.5.0-beta ile çalışmaz . Olarak değiştirilmelidir containsKey(key: string): boolean;
.
İşte @dmck'ten ilham alan daha genel bir Sözlük uygulaması
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;
}
}
Bir özelliği yok saymak istiyorsanız, soru işareti ekleyerek özelliği isteğe bağlı olarak işaretleyin:
interface IPerson {
firstName: string;
lastName?: string;
}
Şimdi, daktiloda güçlü yazılan, sorgulanabilir koleksiyonlar sağlayan bir kütüphane var .
Bu koleksiyonlar:
Kütüphaneye ts-generic-collections-linq adı verilir .
GitHub'daki kaynak kodu:
https://github.com/VeritasSoftware/ts-generic-collections
NPM:
https://www.npmjs.com/package/ts-generic-collections-linq
Bu kütüphane ile, koleksiyonlar oluşturabilir (gibi List<T>
) ve aşağıda gösterildiği gibi sorgulayabilirsiniz.
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; }'.