带有泛型的 TypeScript 接口(interface)函数类型

标签 typescript

我最近在开源存储库中发现了以下代码字节:

interface Use<I, C = context<I>> { 
   <O>(fn: avvio.Plugin<O, I>, options?: O): C; 
} 

简化为:

interface F<A> {
  <B>(foo: A, bar: B): A;
}

我将如何调用 B 泛型?

我正在努力寻找它的示例用法,即使在 TS Playground 中我也无法理解它。我把这段代码放在一个 Playground 你可以查看 here .

最佳答案

它是一个带有通用参数的函数的接口(interface)。这是一个例子:

const funcTwo: F<string> = <T>(foo: string, bar: T) => {
  return `${foo} ${bar}`;
}

console.log(funcTwo('Hello', 7));

更新:添加一个实际示例,可以说明它为何有用。在没有上下文的情况下很难想出一个例子,但这是我不费力思考的最佳尝试:

class UniqueCounter<T> {

  private underlyingSet = new Set<T>();

  constructor(
    private hashingFunc: <V>(value: V) => T,
  ) {

  }

  add<V>(thing: V) {
    const hash = this.hashingFunc(thing);
    this.underlyingSet.add(hash);
  }

  count() {
    return this.underlyingSet.size;
  }

}

此类尝试计算您拥有的某物的唯一实例的数量。但是,默认集使用 === 来表示对象,但这不是我想要的。相反,我对我的特定对象有某种哈希算法。虽然,在某些情况下,我散列成字符串,而在其他情况下,我散列成数字(我散列成的东西是 T)。

我无法将 V 添加到类泛型中,因为那样它就只能计算一种类型的对象。也许我可以通过使用我分配的某种唯一 ID 来散列 PersonEmployee 以及 EquipmentRoom到所有这些类。

我无法将 T 添加到哈希函数的类型参数,因为我需要使用 T 定义 underlyingSet

更新2:

忽略之前的更新,因为它与当前的问题无关。您显示的类型:

interface F<A> {
  <B>(foo: A, bar: B): A;
}

不等于:

interface F<A, B> {
  (foo: A, bar: B): A;
}

假设我们有一个哈希工厂,它可以神奇地创建哈希对象,但它们只能哈希为一种类型的 key 。换句话说,您可以创建一个“将任何内容哈希为字符串”对象或“将任何内容哈希为数字”对象。我们可以将类定义为:

class HashingFactory<T> {

  createHasher<V>(): Hasher;

}

但是,返回类型是什么?我们如何定义Hasher?如果我们将其定义为:

interface Hasher<K, V> {
  hash(value: V): K;
}

然后我们正在创建一些只能对一种类型的输入进行哈希处理的东西(例如,它只能将 Employee 哈希为数字)。但是我们神奇的哈希器可以将任何对象哈希为数字。正确的接口(interface)是:

interface Hasher<K> {
  <V>hash(value: V): K;
}

现在我们可以正确地表示一个对象,可以将 Employee 或 Room 或 Person(或其他任何东西)转换为数字。

关于带有泛型的 TypeScript 接口(interface)函数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55604589/

相关文章:

node.js - Typescript+Node.js 中的 os.EOL

typescript - 如何获得元组元组的扁平元组类型?

javascript - 使用 Angular 2 中的服务将数据从一项服务传递到另一项服务

javascript - 如何返回从输入对象推断键的对象?

node.js - 关系中的 TypeORM OneToMany 过滤器不影响结果

javascript - 忽略负鼠断路器中的 HTTP 404 错误

javascript - Angular 12.1 使用 typescript 添加 html 元素

typescript - 如何使用 tslint 对整个文件夹进行 lint

typescript - 创建继承@Body() 或@Param() 装饰器的自定义NestJs 装饰器?

Javascript:类实例初始化与继承