typescript - 为什么 TypeScript 在实现泛型接口(interface)时无法推断出函数参数的类型?

标签 typescript generics

我在 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:

enter image description here

现在,我可以通过向 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/

相关文章:

Java 泛型形式参数

reactjs - 如何解析 "ethereum.request cannot find name ' 以太坊'"

javascript - 是否可以通过装饰器知道类中定义了哪些方法和属性

javascript - 如何使用 WebStorm 在 TypeScript 而不是 JavaScript 中创建 Cucumber 步骤定义文件?

javascript - Angular 等待 module.run 中的 promise

generics - Typescript 泛型约束扩展了其他泛型类型

java - 一般问题 : T extends interface type. 无法调用方法来返回扩展类型的对象?

javascript - TypeScript:构造函数中的位置或命名参数

c# - 使用泛型和 'new' 修饰符隐藏父成员时的 C# 继承问题

swift - 为 Swift 中的运算符转义闭包