首页 > 解决方案 > 在 TypeScript 中的对象内查找类型

问题描述

我正在尝试在对象中引入查找类型。假设我的对象看起来像

class PersonList {
  persons = {
    john: 'description of john',
    bob: 'description of bob'
  }
}

我想要一个 getter 来获取一个人,persons但不指定persons对象。

来自getProperty文档

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];  // Inferred type is T[K]
}

想要有一个obj我想在我的吸气剂中摆脱的东西。我试过代理吸气剂,但没有成功:

class PersonList {
  persons = {
    john: 'description of john',
    bob: 'description of bob'
  };

  getPerson(name) {
    return this.getProperty(this.persons, name);
  }

  private getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];  // Inferred type is T[K]
  }
}

可悲的是,这在尝试执行类似的操作时不会引发错误personList.getPerson('someonenotincluded');- 而且自动完成功能也不起作用。

标签: typescript

解决方案


我会采用该内联类型并将其命名(但请继续阅读,您不必这样做

interface Persons {
  john: string;
  bob: string;
}

然后你可以使用keyof Persons作为参数类型getPerson

class PersonList {
  persons: Persons = {
    john: 'description of john',
    bob: 'description of bob'
  };

  getPerson(name: keyof Persons) {
    return this.persons[name];
  }
}

那么如果plPersonList

console.log(pl.getPerson('john')); // Works
console.log(pl.getPerson('someonenotincluded')); // Error

住在操场上

但是,如果你更喜欢保持它内联,你可以使用keyof PersonList['persons']作为参数类型:

class PersonList {
  persons = {
    john: 'description of john',
    bob: 'description of bob'
  };

  getPerson(name: keyof PersonList['persons']) {
    return this.persons[name];
  }
}

住在操场上


在您问过的评论中:

是否可以在抽象类中实现它?...在抽象类中实现getter会很棒,但到目前为止我还没有找到解决方案。

...带有指向此代码模板的链接:

abstract class AbstractPersonList {
  protected abstract persons: { [name: string]: string };
}

class Persons extends AbstractPersonList {
  persons = {
    john: 'this is john',
  }
}

class MorePersons extends AbstractPersonList {
  persons = {
    bob: 'this is bob',
  }
}

您可以参数化AbstractPersonList

abstract class AbstractPersonList<T extends {[name: string]: string}> {
// ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  protected abstract persons: T;
  public getPerson(name: keyof T): string {
    return this.persons[name];
  }
}

然后你会有:

class Persons extends AbstractPersonList<{john: string}> {
// -------------------------------------^^^^^^^^^^^^^^^^
  persons = {
    john: 'this is john',
  }
}

class MorePersons extends AbstractPersonList<{bob: string}> {
// -----------------------------------------^^^^^^^^^^^^^^^
  persons = {
    bob: 'this is bob',
  }
}

这导致了这些结果,我认为这是您正在寻找的:

let n = Math.random() < 0.5 ? 'john' : 'bob';

const p = new Persons();
console.log(p.getPerson('john'));  // Works
console.log(p.getPerson('bob'));   // FAILS: Argument of type '"bob"' is not assignable to parameter of type '"john"'.
console.log(p.getPerson(n));       // FAILS: Argument of type 'string' is not assignable to parameter of type '"john"'.

const mp = new MorePersons();
console.log(mp.getPerson('john')); // FAILS: Argument of type '"john"' is not assignable to parameter of type '"bob"'.
console.log(mp.getPerson('bob'));  // Works
console.log(mp.getPerson(n));      // FAILS: Argument of type 'string' is not assignable to parameter of type '"bob"'.

住在操场上


推荐阅读