是否可以强制所有类公共方法使用打字稿返回相同的类型?

dis*_*nte 2 typescript

我正在构建一些辅助类来操作或获取一些特定的 DOM 元素类型。

HTMLDivElementHelper所以我有一个所有公共方法都应该返回的例子HTMLDivElement

这些方法至少包含 1 个参数,但也可以包含 2 个。

我试图通过界面或类似的方式强制执行此操作,但我找不到如何执行此操作。

如果我使用class MyHelper implements Record<string, () => HTMLDivElement> Typescript 抱怨Property 'setValue' of type '(selector: string) => HTMLDivElement' is not assignable to 'string' index type '() => HTMLDivElement'.(2411)

游乐场在这里

这可能吗?

jca*_*alz 5

如果您希望您的类具有函数成员,那么您不能使用字符串索引签名,也不能说implements Record<string, XXX>因为当您的键类型为 时,实用程序Record<K, V>类型与索引签名相同string


相反,您可以提出一个泛型类型CheckMethods<T>来充当 类的约束。这个想法是,您编写class MyHelper implements CheckMethods<MyHelper> { /* ... */ }, where CheckMethods<MyHelper>will 评估为与MyHelper当且仅当所有方法(好吧,函数值成员)都是您希望它们成为的类型时兼容的东西。这种自我参照约束被称为“F-bounded quantification”。这是一个可能的实现:

type CheckMethods<T> = { [K in keyof T]: T[K] extends Function ?
  ((selector: string, options: any) => HTMLDivElement) : T[K] }
Run Code Online (Sandbox Code Playgroud)

CheckMethods<T>是一个映射类型K,其中每个属性键T都映射到一个新的属性类型。使用条件T[K]类型检查旧属性类型以查看它是否为 a。如果不是,我们只需将其映射到自身,,这将始终为真。如果它一个函数,那么我们将它映射到一个特定的函数类型,它将与最多两个相同类型参数的任何函数一起使用(有关更多信息,请参阅函数兼容性文档。FunctionT[K](selector: string, options: any) => HTMLDivElement

让我们看看它的实际效果:

class MyHelper implements CheckMethods<MyHelper> {

  nonMethod = 123; // okay

  setValue(selector: string): HTMLDivElement { // okay
    return document.createElement('div');
  }

  setTest(selector: string, options: { options: string }): HTMLDivElement { // okay
    return document.createElement('div');
  }

  badParameter(selector: number): HTMLDivElement { // error!
     return document.createElement("div");
  } 

  badReturn(selector: string) { return 3 } // error!

}
Run Code Online (Sandbox Code Playgroud)

看起来不错!

Playground 代码链接