打字稿:实现通用接口

时间:2017-04-05 17:52:35

标签: generics typescript typescript-generics

考虑以下通用接口:

interface Extractor<T> {
  extractCandidate(): T;
  process(candidate: T): T;
}

从概念上讲,每个Extractor实现负责从某个数据源中提取特定类型的对象。 Extractor的使用者可以使用extractCandidate()提取候选对象,或者,给定任何候选对象,对其执行一些进一步处理以使用process()获得对象的更精细版本。

现在,我们假设我为类Extractor实现MyClass,如下所示:

class MyClass {
  a: string;
  b: string;
}

class MyExtractor implements Extractor<MyClass> {
  extractCandidate() {
    //Some dummy logic
    return new MyClass();
  }
  process(candidate) {
    //Some dummy logic
    let res = new MyClass();
    res.a = candidate.a;
    return res;
  }
}

现在让我说我实例化MyExtractor并使用它:

let myExtractor = new MyExtractor();
let processed = myExtractor.process('blah');

问题1 :为什么这不会产生编译时错误?根据{{​​1}}接口的定义,我希望编译器不允许我用Extractor的实例调用myExtractor.process(),或者至少使用结构上的东西兼容。

问题2 :如何执行所需的行为?我是否只需断言MyClass的{​​{1}}参数属于candidate类型?

我怀疑这与TypeScript的结构化打字系统有关,但在阅读some related questionsFAQ之后,我就会这样做。我还不确定它在这里具体适用。

我的手稿版本是2.1.4。

1 个答案:

答案 0 :(得分:3)

您为MyExtractor发布的代码具有process方法的以下签名:

process(candidate: any): MyClass

原因是您尚未为candidate指定类型,因此默认情况下为any
编译器不会抱怨,因为它满足candidate: T(因为any可以是T)。

如果您将代码更改为:

process(candidate: MyClass) {
    ...
}

然后为:

let processed = myExtractor.process('blah');

你会得到:

  

类型的争论&#34;&#34; blah&#34;&#39;不能分配给类型的参数   &#39; MyClass的&#39;

您可以使用导致编译器抱怨的--noImplicitAny flag来避免这种情况:

process(candidate) {
    ...
}

话说:

  

参数&#39;候选人&#39;隐含地有一个“任何”的型

修改

候选人不能被&#34;其他任何&#34;,允许any(并且这是默认值),这是一个很好的理由,例如用于重载:

process(candidate: string): MyClass;
process(candidate: MyClass): MyClass;
process(candidate: any) {
    ...
}
相关问题