在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型

Posted

技术标签:

【中文标题】在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型【英文标题】:In Typescript how to get the generic return type of a method on a class instantiated in a factory(ish) function 【发布时间】:2021-10-11 14:48:21 【问题描述】:

在下面的示例代码中,TypeScript 无法在fooBar 函数中推断出泛型类型U,因此fooRef.doIt() 的返回类型为unknown。为什么会这样?为了获得正确的返回类型,我需要修改什么?

interface Foo<T> 
  foo(): T;


class Bar implements Foo<string> 
  foo(): string 
    return 'Bar';
  


class Baz implements Foo<number> 
  foo(): number 
    return 43;
  


class FooRef<T extends Foo<U>, U> 
  constructor(private instance: T) 

  doIt() 
    return this.instance.foo();
  


function fooBar<T extends Foo<U>, U>(foo: new (...args: any[]) => T) 
  return new FooRef(new foo());


const barRef = fooBar(Bar);
barRef.doIt(); // unknown, expected string

const bazRef = fooBar(Baz);
bazRef.doIt(); // unknown, expected number

【问题讨论】:

我很难想出一个准确描述我的问题的标题。如果您有更好的建议,请告诉我。 鉴于此示例代码,我将删除您的T,仅使用U,如this。如果由于某种原因您需要T,我会删除U 并像this 一样重写它(并使用ReturnType&lt;T["foo"]&gt;T extends Foo&lt;infer U&gt; ? U : never 之类的东西从T 计算U)。如果其中任何一个对您有用,我将很乐意写下答案。让我知道您想在这里看到哪些(如果有的话)。如果两者都没有,请详细说明缺少的内容。 @jcalz 太棒了!我确实需要知道扩展 Foo 的具体类的类型(我应该将 instance 公开),所以你的第二个选项应该可以工作。如果您继续写一个答案,显示使用ReturnTypeinfer 的示例,那就太好了。 【参考方案1】:

这个答案的灵感来自@jcalz 在 cmets 中的建议。正如他所建议的那样,我无法使用infer 使其工作,但他使用ReturnType 的建议按预期工作,这就是我在这里使用的。

interface Foo<T> 
    foo(): T;


class Bar implements Foo<string> 
    foo(): string 
        return 'Bar';
    


class Baz implements Foo<number> 
    foo(): number 
        return 43;
    


class FooRef<T extends Foo<U>, U = ReturnType<T["foo"]>> 
    constructor(public instance: T)  

    doIt(): U 
        return this.instance.foo();
    


function fooBar<T extends Foo<any>>(foo: new (...args: any[]) => T) 
    return new FooRef(new foo());


const barRef = fooBar(Bar);
barRef.instance // (property) FooRef<Bar, string>.instance: Bar
console.log(barRef.doIt().toUpperCase()); // "BAR"

const bazRef = fooBar(Baz);
bazRef.instance // (property) FooRef<Baz, number>.instance: Baz 
console.log(bazRef.doIt().toFixed(2)) // "43.00"

【讨论】:

以上是关于在Typescript中,如何在工厂(ish)函数中实例化的类上获取方法的通用返回类型的主要内容,如果未能解决你的问题,请参考以下文章

在工厂函数之外公开本地 TypeScript 类的类型

是否可以在 TypeScript 中声明和调用函数字典?

如何从 TypeScript 函数返回一个类?

使用 netTcpBinding 的慢(ish)WCF 连接速度

14-TypeScript简单工厂模式

TypeScript:带有自定义方法的工厂 - 第三步