如何覆盖扩展记录的泛型类参数?

How to overwrite generic class argument that extends record?

提问人:Eggy 提问时间:11/14/2023 最后编辑:Eggy 更新时间:11/14/2023 访问量:58

问:

我有一个和类。该类接受 2 个泛型参数:和 . 应该是某种类,而是以特定接口作为值的子集。现在,我的目标是创建子类,该子类将强制某些特定属性存在于 上,以便我可以强制使用该属性接口的某些自定义实现。ParentChildParentResultParentBuilderMapResultParentBuilderMapResultParentBuilderMap

我试图用 覆盖属性,但这会产生一个错误,指出这种类型不能分配给 ,我觉得这很奇怪,因为它将具有相同的键(或更多应该没问题)。Omit<A, keyof B> & BParentBuilderMap

下面是上述描述的演示实现

type Overwrite<A, B> = Omit<A, keyof B> & B;

interface Builder<Result> {
  build(): Result;
}

class SuperSecretBuilder implements Builder<string> {
  build() {
    return "lorem ipsum";
  }

  secret() {
    return "p4ssw0rd";
  }
}

type BuilderMap<Result> = Partial<Record<keyof Result, Builder<unknown>>>;

class Parent<Result, ParentBuilderMap extends BuilderMap<Result>> {
  doWork<Key extends keyof ParentBuilderMap>(key: Key, cb: () => ParentBuilderMap[Key]) {
    // tbd
  }
}

class Child<
  Result,
  ChildBuilderMap extends Overwrite<BuilderMap<Result>, { value: SuperSecretBuilder }>,
> extends Parent<Result, ChildBuilderMap> {
  doSecretWork() {
    // This method should resolve callback return value to SuperSecretBuilder based on provided key.
    this.doWork("value", () => {
      const builder = new SuperSecretBuilder();

      console.log(builder.secret());

      return builder;
    });
  }
}

和游乐场链接

TypeScript 继承 TypeScript-泛型

评论

0赞 jcalz 11/14/2023
你这里有两个错误;你具体问的是哪一个?一个是约束满足错误(这可能是由于编译器缺乏对泛型条件类型执行抽象分析的能力),另一个是实现返回类型错误(这是因为泛型类型可能比约束,即使在键处也是如此;不确定为什么你希望它在那里是泛型的)。如果您能清除另一个,我很乐意调查并尝试解决其中一个问题。value
0赞 Eggy 11/14/2023
Parent类不接受兼容类型(在我看来)是这里的问题。至于为什么我在方法中需要泛型:我想在类中做一些操作。这很好用,因为有 ( 来自 .现在,我有几个子类。它们都需要对 中的某些属性进行一些具体的实现。因此,上述的目标是提取到抽象类中,以便它可以被具体类(应该扩展类)重用。doWorkBuilderParentBuilder<unknown>BuilderMap<Result>ParentBuilderBuilderMapdoSecretWorkChild
0赞 Eggy 11/14/2023
此外,和类(以及可能随后的任何子类)都在实现 .我省略了这一点,因为它只会使视图混乱。ParentChildBuilder<Result>
0赞 Eggy 11/14/2023
至于为什么我在方法中需要泛型:我想确保从回调返回的构建器匹配。如果没有泛型,我可以通过 的任何实现。偶数来自这样,当调用方法时,我可以正确解析(这发生在类中)。doWorkParentBuilderMap<Result>BuilderBuilderMapBuilderbuildParent
0赞 jcalz 11/14/2023
(1) 如果你问的是约束满足错误(在 下)而不是回调错误(在 下),那么请编辑代码以解决后一个错误,这样就不会分心,所以这是一个最小的可重现示例(例如,只需在返回行中断言)。一旦你这样做了,这种方法是否满足你的需求?我不确定什么会买你,因为如果已经有房产,可能会发生奇怪的事情。如果有帮助,我会写一个答案来解释;如果没有,我错过了什么?ChildBuilderMap() => {as ChildBuilderMap["value"]OverwritevalueResult

答: 暂无答案