具有泛型的TypeScript接口函数类型

时间:2019-04-10 04:03:40

标签: 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中也无法理解。我将这段代码放在可以查看here的操场上。

1 个答案:

答案 0 :(得分:1)

这是带有通用参数的函数的接口。这是一个示例:

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

UPDATE2:

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

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

不等同于:

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

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

class HashingFactory<T> {

  createHasher<V>(): Hasher;

}

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

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

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

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

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