我在 Visual Studio 2015 中编写 TypeScript,安装了 2.3.3.0 版的语言服务扩展。我在项目的 tsconfig.json
中将 noImplicitAny
参数设置为 true
。
给定这个简单的示例代码:
interface ITransformer<TInput, TOutput> {
transform(input: TInput): TOutput;
}
class Input {
name: string;
}
class Output {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Test {
name: string;
}
class Transformer implements ITransformer<Input, Output> {
transform = (input) => new Output(input.name);
}
TS 编译器给我一个错误:TS7006: Parameter 'input' implicitly has an 'any' type
:
现在,我可以通过向 input
参数添加类型注释来轻松修复此错误:
class Transformer implements ITransformer<Input, Output> {
transform = (input: Input) => new Output(input.name);
}
但我的问题是,我为什么必须这样做?在我看来,应该从接口(interface)实现中的 TInput
类型推断出该参数的类型(在本例中为 Input
)。
更令人担忧的是,我可以很高兴地这样做:
class Transformer implements ITransformer<Input, Output> {
transform = (input: Test) => new Test();
}
它接受并返回一个完全不同的类型,或者类型参数都没有引用,而且编译器似乎没有问题......
来自 C# 背景,这似乎是错误的。我错过了什么?
最佳答案
在实现ITransformer
接口(interface)时,您可以使用不同的签名覆盖transform
,例如:
class Transformer implements ITransformer<Input, Output> {
transform(input: string): Output;
transform(input: number): Output;
transform(input: Input): Output;
transform(input: any): Output {
// ...
}
}
您不必只在接口(interface)中实现签名。因此,您必须隐式编写类型:
transform = (input: Input) => new Output(input.name);
至于为什么会这样:
transform = (input: Test) => new Test();
那是因为TypeScript is based on structural subtyping并且这两种类型具有相同的结构 ({ name: string }
)。尝试向其中一个属性添加另一个属性,您会收到错误消息。
我想指出的最后一件事是,您定义类方法的方式实际上不会创建方法,而只是具有函数类型的成员:
class Test {
method1() { }
method2 = () => {}
}
这里只有 method1
是真正的方法,而 method2
只是在构造函数中分配的属性,它不会成为原型(prototype)的一部分,你赢了如果您扩展该类,则无法覆盖它。
这是这段代码的编译版本:
var Test = (function () {
function Test() {
this.method2 = function () { };
}
Test.prototype.method1 = function () { };
return Test;
}());
这种方法很好并且正在使用,但请注意。
关于typescript - 为什么 TypeScript 在实现泛型接口(interface)时无法推断出函数参数的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44718470/