简体   繁体   English

打字稿中的抽象函数返回类型

[英]Abstract function return type in typescript

It seems that defining an abstract function with generic return type is not possible with typescript (I am using ts 3.2.4) or I am missing something. 似乎用typescript定义一个具有泛型返回类型的抽象函数(我使用ts 3.2.4)或者我遗漏了一些东西。

For instance: 例如:

abstract class Foo {
    abstract func<T>() : T;
}

class Bazz extends Foo {
    func() { return 1; }
}

will give an error: 会出错:

TS2416: Property 'func' in type 'Bazz' is not assignable to the same property in base type 'Foo'. TS2416:类型'Bazz'中的属性'func'不能分配给基类型'Foo'中的相同属性。 Type '() => number' is not assignable to type '() => T'. 类型'()=>数字'不能分配给'()=> T'。 Type 'number' is not assignable to type 'T'. 类型“数字”不能分配给“T”类型。

So, is it possible to define an abstract function that will have the generic return type? 那么,是否可以定义一个具有泛型返回类型的抽象函数?

Edit: 编辑:

So, it turns out that using unknown work as expected and it can be used as the return type in an abstract function. 因此,事实证明,按预期使用未知工作,它可以用作抽象函数中的返回类型。 But, let's consider this: 但是,让我们考虑一下:

abstract class Foo{
    getFuncResult() {
        return this.func();
    }
    abstract func() : unknown;
}

class Bazz extends Foo {
    func() { return 1; }
}

let foo: Foo = new Bazz();
foo.func(); // unknown

let bazz = new Bazz() 
bazz.func() // number
bazz.getFuncResult() // unknown

I would expect that the getFuncResult on the Bazz will have the same type signature as derived func (number). 我希望Bazz上的getFuncResult与派生的func(数字)具有相同的类型签名。 So, this is more a question about type inference for Typescript. 所以,这更像是关于Typescript的类型推断的问题。

The problem is where you put the type parameter. 问题在于您放置type参数。 If the type parameter is on the method, then that method must be generic in derived class. 如果类型参数在方法上,则该方法在派生类中必须是通用的。 The contract that is specified by that method means we must always be able to call it with any T (ie the caller decides with what T to call). 由该方法指定的合同意味着我们必须始终能够用任何T调用它(即调用者决定使用什么T调用)。 So this code need to work: 所以这段代码需要工作:

let a: Foo = new Bazz()
a.fun<string>() // method is generic caller decides `T`

You want to place the type parameter on the class, and fix the type parameter when inheriting in Bazz 您希望将类型参数放在类上,并在Bazz中继承时修复type参数

abstract class Foo <T>{
    abstract func() : T;
}

class Bazz extends Foo<number> {
    func() { return 1; }
}

let foo: Foo<number> = new Bazz();
foo.func(); //ok result is numebr

let fooStr: Foo<string> = new Bazz() // error, different T 

Edit 编辑

If you don't care what the return type is in the base class and you just want the derived class to create the method, you could use unknown as the return type. 如果您不关心基类中的返回类型,并且您只希望派生类创建该方法,则可以使用unknown作为返回类型。 If you have a reference to the abstract class and invoke the method it will return unknown if you have a reference to a derived class it will return the apropriate type: 如果你有一个对抽象类的引用并调用该方法,那么如果你有一个派生类的引用,它将返回unknown ,它将返回适当的类型:

abstract class Foo{
    abstract func() : unknown;
}

class Bazz extends Foo {
    func() { return 1; }
}

let foo: Foo = new Bazz();
foo.func(); // unknown

let bazz = new Bazz() 
bazz.func() // number

Edit 编辑

With regard to using func in another function and expecting the type of that to be relative to func typescript will not help you there, at least not by default. 关于在另一个函数中使用func并期望它的类型相对于func typescript将无法帮助你,至少在默认情况下不会。 By default getFuncResult will be typed with what information is known in the base class. 默认情况下,将使用基类中已知的信息键入getFuncResult Without using a class type parameter (and I do think you should look into that) a solution is to use a type query on the polymorphic this type. 不使用类类型参数(我认为你应该考虑一下),解决方案是对this类型的多态使用类型查询。 This will type the return relative to whatever the current class is but you will need to use a type assertion inside the function to get things to work: 这将输入相对于当前类的返回值,但是您需要在函数内部使用类型断言来使事情起作用:

abstract class Foo{
    getFuncResult() : ReturnType<this['func']> {
        return this.func() as any;
    }
    abstract func() : unknown;
}

class Bazz extends Foo {
    func() { return 1; }
}

let foo: Foo = new Bazz();
foo.func(); // unknown

let bazz = new Bazz() 
bazz.func() // number
bazz.getFuncResult() // number

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

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