考虑以下通用接口:
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 questions和FAQ之后,我就会这样做。我还不确定它在这里具体适用。
我的手稿版本是2.1.4。
答案 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) {
...
}