首页 > 解决方案 > 键入我们知道是字符串的对象的属性

问题描述

我在一个类中有一个方法,它的调用签名是:

async where(
    prop: K & string,
    value: PropType<T, K> | [IComparisonOperator, PropType<T, K>],
    options: IDexieListOptions<T> = {}
  ) { ...}

该类的定义将 T 和 K 定义为:

class MyClass<T extends Model, K extends keyof T> { ... }

PropType 类型就是这样:

type PropType<TObj, TProp extends keyof TObj> = TObj[TProp]

在同一类的另一种方法中,我尝试where像这样使用:

  async since(datetime: epoch) {
    return this.where("lastUpdated", [">", datetime]);
  }

lastUpdated属性是扩展的有效属性,Model当然<T>它也是一个“字符串”,因此它似乎符合签名where()但我得到了这个错误:

错误信息

'"lastUpdated"' 可分配给'K' 类型的约束,但'K' 可以用约束'string | 的不同子类型实例化。号码 | 象征'。

有谁知道如何解决这个问题?


这个Model类——我应该从一开始就包括在内——被定义为:

export class Model {
  public id?: string;
  public lastUpdated?: number;
  public createdAt?: number;
}

我确实想知道可选的事实lastUpdated是否是一个促成因素,但即使将其设为必需似乎也没有什么区别。

标签: typescript

解决方案


问题是您的类将第二个泛型参数定义为的K任何子类型,但您在函数keyof T中使用具体的子类型时还不知道。这是不允许的,这里有详细说明:https ://stackoverflow.com/a/59363875/1628117"lastUpdated"since()T

上述注释中@jcalz 的解决方案是通过让函数本身决定调用时where适合的子类型来解决此问题的方法。keyof T

class MyClass<T extends Model> {

  async where<K extends keyof T>(
    prop: K, ...
  ) { }

  ...

}

推荐阅读