首页 > 解决方案 > 基于模板参数访问 Typescript 对象属性

问题描述

我想创建一个按字段查找项目的 Typescript Collection 类,如下所示:

class Collection<T, K keyof T> {
    private _items: T[];

    public isItemInCollection(item: T) {
        return _items.find((a) => a[K] === item[K], this._items) !== undefined;
    }
 }

然后我想用这样的东西来实例化它:

interface MyItem {
    idField: string,
    otherField: number,
}

class ItemCollection: MyCollection<MyItem, 'idField'> { }

不幸的是,这不起作用,我得到一个错误,引用item[K]说 K 是一种类型而不是一个值。我了解导致错误的原因,我只是不知道如何解决。这在 Typescript 中是否可行?

标签: typescripttemplates

解决方案


您需要K在运行时的某个地方传递一个类型的值才能使其工作。如果我正确理解您的Collection课程的要点,您将需要一个实际的数组T和 type 的值K。获取这些值的好地方是在您构建新Collection实例时。也就是说,让构造函数将它们作为参数:

class Collection<T, K extends keyof T> {
  private _items: T[];
  private _idKey: K;
  constructor(items: T[], idKey: K) {
    this._items = items;
    this._idKey = idKey;
  }

  public isItemInCollection(item: T) {
    return (
      this._items.find(a => a[this._idKey] === item[this._idKey]) !== undefined
    );
  }
}

然后你可以按照你的期望使用它(我想是的,无论如何......你实际上并没有展示你的用例)。给定这些类型和对象:

interface MyItem {
  idField: string;
  otherField: number;
}
const itemA: MyItem = { idField: "A", otherField: 1 };
const itemB: MyItem = { idField: "B", otherField: 2 };
const itemC: MyItem = { idField: "C", otherField: 3 };

const items: MyItem[] = [itemA, itemB];

您可以构建一个新的Collection

const itemCollection = new Collection(items, "idField");

通过类型推断,itemCollection是类型Collection<MyItem, "idField">。并使用它:

console.log(itemCollection.isItemInCollection(itemA)); // true
console.log(itemCollection.isItemInCollection(itemC)); // false
console.log(
  itemCollection.isItemInCollection({ idField: "A", otherField: 2893 })
); // true so be careful

好的,希望有帮助。祝你好运!

链接到代码


推荐阅读