I would like my javascript data to be like this:
"dogs": {
"ada": {
age: 7,
breed: poodle
},
"levin": {
age: 5,
breed: shitzu
},
...
}
Where the name is an object key. I have this typescript class:
export class Dog {
[dogName: string]: DogDetails;
}
The only way I could see that I could encapsulate methods to create accesssors is by adding these static methods to Dog
:
public static getDogName(dog: Dog): string {
return Object.keys(dog).toString();
}
public static getDogDetails(dog: Dog): DogDetails {
return dog[Dog.getDogName(dog)];
}
Which is pretty horrible. One reason being is that static access is required:
Dog.getDogName(dog) // this is how it must be done
And seems so contrary to how this should be written, which would be:
dog.getName(); // this unfortunately can't be done
The situation would be much nicer if there was a way to get access to the index signature value. However I could not find any way to achieve this. Is there a way or is there a better way to write this class?
Note that this is not possible with classes using index signatures:
public getName(): string { // this won't work
Object.keys(this).toString();
}
Since it complains Property 'getName' of type '() => string' is not assignable to string index type 'DogDetails'
Update after answer from @amiramw and comments conversation:
The angular component where this is being used is:
<ion-list *ngFor="let dog of dogs">
<ion-item>
<ion-avatar item-start>
<img src="assets/img/dog.jpg"/>
</ion-avatar>
<h4>{{Dog.getName(dog)}}</h4>
<p>{{Dog.getDogDetails(dog).breed}}</p>
</ion-item>
</ion-list>
After the feedback it seems I'll need to write:
<ion-list *ngFor="let dogName of getDogNames()">
<ion-item>
<ion-avatar item-start>
<img src="assets/img/dog.jpg"/>
</ion-avatar>
<h4>{{dogName}}</h4>
<p>{{getDogDetails(dogName).breed}}</p>
</ion-item>
</ion-list>
Where getDogNames()
is:
public getDogNames(): string[] {
if (this.dogs) {
return Object.keys(this.dogs);
} else {
return new Array<string>();
}
}
And getDogDetails()
is:
public getDogDetails(name: string): DogDetails {
return this.dogs[name];
}
Which works but isn't what I was looking for. I will give @amiramw credit for the suggestion as to a solution to my overall problem.
However I'd much appreciate knowing if there is a way to obtain the typescript index signature value??
You can create an interface for each dog's data and define a map from string to that interface. The interface can be named (for reuse) or anonymous:
enum Breed {
poodle,
shitzu
}
let dogs : { [key:string]: {age: number, breed: Breed} } = {
"ada": {
age: 7,
breed: Breed.poodle
},
"levin": {
age: 5,
breed: Breed.shitzu
}
};