打字稿索引签名访问器

typescript index signature accessors

我希望我的 javascript 数据是这样的:

"dogs": {
    "ada": {
        age: 7,
        breed: poodle
    },
    "levin": {
        age: 5,
        breed: shitzu
    },
    ...
}

其中名称是对象键。我有这个打字稿 class:

export class Dog {
  [dogName: string]: DogDetails;
}

我认为可以封装方法来创建访问器的唯一方法是将这些静态方法添加到 Dog:

  public static getDogName(dog: Dog): string {
    return Object.keys(dog).toString();
  }

  public static getDogDetails(dog: Dog): DogDetails {
    return dog[Dog.getDogName(dog)];
  }

这太可怕了。原因之一是需要静态访问:

Dog.getDogName(dog)  // this is how it must be done

这似乎与应该如何编写相反:

dog.getName();  // this unfortunately can't be done

如果有一种方法可以访问索引签名值,情况会好得多。但是我找不到任何方法来实现这一目标。有没有办法或者有更好的方法来写这个class?

请注意,使用索引签名的 classes 无法做到这一点:

public getName(): string {   // this won't work
    Object.keys(this).toString();
}

因为它抱怨 Property 'getName' of type '() => string' is not assignable to string index type 'DogDetails'


@amiramw 的回答和评论对话后更新:

正在使用的 angular 组件是:

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

反馈后看来我需要写:

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

其中 getDogNames() 是:

  public getDogNames(): string[] {
    if (this.dogs) {
      return Object.keys(this.dogs);
    } else {
      return new Array<string>();
    }
  }

getDogDetails()是:

  public getDogDetails(name: string): DogDetails {
    return this.dogs[name];
  }

哪个有效,但不是我想要的。对于解决我的整体问题的建议,我将赞扬@amiramw。

不过,我很想知道是否有办法获取打字稿索引签名值??

您可以为每只狗的数据创建一个接口,并定义一个从字符串到该接口的映射。接口可以命名(为了重用)或匿名:

enum Breed {
    poodle,
    shitzu
}
let dogs : { [key:string]: {age: number, breed: Breed} } = {
    "ada": {
        age: 7,
        breed: Breed.poodle
    },
    "levin": {
        age: 5,
        breed: Breed.shitzu
    }
};