简体   繁体   English

如何推断在Typescript方法中绑定到参数化类的通用参数的通用返回类型?

[英]How to infer the generic return type that is bound to a generic parameter of a parameterized class in a typescript method?

I have the following superclass, T is supposed to be the type the API returns 我有以下超类,T应该是API返回的类型

export class Command<T> {

}

This is a login command that extends the command: 这是一个扩展命令的登录命令:

export class LoginCommand extends Command<LoginResult> {
    username: string;
    password: string;
}

And the return object: 和返回对象:

export class LoginResult {
    success: boolean;
    token: string;
}

When calling the method: 调用方法时:

public call<R>(command: model.command.Command<R>): R {
    return null as R; // code omitted
}

with the following parameter: 具有以下参数:

const cmd = new LoginCommand();
const success = this.call(cmd).success;

it yields an error : [ts] Property 'success' does not exist on type '{}' 它会产生错误: [ts]类型“ {}”上不存在属性“成功”

Question 1 : How to modify the method signature to correctly infer the R from Command as the return type? 问题1 :如何修改方法签名以正确地从Command推断R为返回类型? I've also tried the following syntax with the same result: 我还尝试了以下语法,结果相同:

    public call<T extends Command<R>, R>(command: T): R

Question 2 : Why is the ask method accepting parameters that do not extend Command? 问题2 :为什么ask方法接受不扩展Command的参数? Passing in a string yields no errors. 传递字符串不会产生任何错误。

The last question is the easiest to answer, your Command base class has no properties or methods so any type will be structurally equivalent to it including a string. 最后一个问题最容易回答,您的Command基类没有属性或方法,因此任何类型在结构上都等同于它,包括字符串。

The other part of the problem is more difficult, if you pass a derived type from a generic type the compiler will not drill down to infer generic parameters. 问题的另一部分更加困难,如果您从泛型类型传递派生类型,则编译器将不会向下钻取以推断出泛型参数。

You could do one of the following: 您可以执行以下操作之一:

Add a with operation to the Command class with操作添加到Command

export class Command<T> {
    private something: "";
    with(fn: (cmd: Command<T>) => T) : T{
        return fn(this);
    }
}

//Usage:
public call<R>(command: Command<R>): R {
    return null as R; // code omitted
}

public doStuff() {
    const cmd = new LoginCommand();
    const success = cmd.with(this.call).success; // Works
}

Add a simple casting method to the base class 向基类添加简单的转换方法

export class Command<T> {
    private something: "";
    asCmd(): Command<T> { return this;}
}

public doStuff() {
    const cmd = new LoginCommand();
    const success = this.call(cmd.asCmd()).success;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM