【问题标题】:Getting the return type of a function which uses generics获取使用泛型的函数的返回类型
【发布时间】:2018-10-04 22:42:22
【问题描述】:

免责声明:以下是过度简化的功能,我知道它们是 没用的

function thinger<T>(thing: T): T {
    return thing;
}

const thing = thinger({ a: "lol" });

thing.a;

上面的代码编译得很好。但我需要将thinger&lt;T&gt; 的结果放入一个对象中。

interface ThingHolder {
    thing: ReturnType<typeof thinger>;
}

const myThingHolder: ThingHolder = {
    thing: thinger({ a: "lol" }),
};

但是我丢失了类型信息,所以myThingHolder.thing.a 不起作用

类型“{}”上不存在属性“a”

所以我尝试了以下

interface ThingHolder<T> {
    thing: ReturnType<typeof thinger<T>>;
}

const myThingHolder: ThingHolder<{ a: string }> = {
    thing: thinger({ a: "lol" }),
};

但是typeof thinger&lt;T&gt; 不是有效的打字稿。

如何获取基于泛型具有不同返回类型的函数的返回类型?

【问题讨论】:

  • 自己搞清楚有什么问题? interface ThingHolder&lt;T&gt; { thing: T } ?
  • 正如我在文章开头的免责声明中一样,我意识到在这个过于简化的示例中我应该这样做,但我的实际用例并不是那么简单。我有一个函数接受许多泛型并返回比这些泛型更复杂的东西(但泛型仍然会影响返回类型)
  • 我可以编写它,但它会非常冗长,并且每次函数更改时都需要重新编写。老实说,即使它一个合理的解决方案,我仍然想要这个问题的答案。
  • 简短的回答是“TypeScript 不能那样做”,因为它既没有 generic valueshigher kinded types 也没有 typeof on arbitrary expressions
  • 这不是我的功能,它是图书馆的。我只对我的问题的答案感兴趣,这是一种获取返回类型受泛型影响的函数的返回类型的方法。或者,解释为什么这是不可能的就足够了。如果不可能,我有更简单的方法来解决我的用例。但如果可能的话,我更愿意这样做。

标签: typescript generics typescript-generics


【解决方案1】:

这可能会解决问题。但是你需要创建一个假类。它之所以有效,是因为类同时是类型和 JS 运行时对象。

// generic function
// we want to get its result, but we cannot do it like
// ReturnType<typeof foo<T>()> // syntax error
const foo = <T,>(arg: T) => ({ test: arg });
// so, let's create a parametric class
class Wrapper<T> {
  // with the only method that uses our "foo"
  wrapped = (arg: T) => foo(arg);   
};
// due to the fact that class is a type we can use it as a type 
// with a generic parameter.
type GetFooResult<T> = ReturnType<Wrapper<T>['wrapped']>
type Bingo = GetFooResult<number>; // { test: number }

TS 游乐场link。基于this answer。感谢@Colin

【讨论】:

    【解决方案2】:

    我不妨把它放在一个答案中,尽管它看起来不能满足您的需求。 TypeScript 目前既没有 generic valueshigher kinded types 也没有 typeof on arbitrary expressions。 TypeScript 中的泛型有点“浅”。据我所知,不幸的是,没有办法描述将类型参数插入泛型函数并检查结果的类型函数:

    // doesn't work, don't try it
    type GenericReturnType<F, T> = F extends (x: T) => (infer U) ? U : never
    
    function thinger<T>(thing: T): T {
      return thing;
    }
    
    // just {}, ?
    type ReturnThinger<T> = GenericReturnType<typeof thinger, T>;
    

    所以我能为您做的就是建议解决方法。最明显的解决方法是使用类型别名来描述 thinger() 返回的内容,然后在多个地方使用它。这是您想要的“向后”版本;不是从函数中提取返回类型,而是从返回类型构建函数:

    type ThingerReturn<T> = T; // or whatever complicated type you have
    
    // use it here
    declare function thinger<T>(thing: T): ThingerReturn<T>;
    
    // and here
    interface ThingHolder<T> {
      thing: ThingerReturn<T>;
    }
    
    // and then this works ? 
    const myThingHolder: ThingHolder<{ a: string }> = {
      thing: thinger({ a: "lol" }),
    };
    

    这有帮助吗?我知道这不是你想要的,但希望这至少是你前进的一条可能的道路。祝你好运!

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-11
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多