获取使用泛型的函数的返回类型

时间:2018-04-24 15:31:24

标签: typescript generics typescript-generics

  

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

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

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

thing.a;

上面的代码转换得很好。但我需要将thinger<T>的结果放入对象中。

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<T>不是有效的打字稿。

如何根据泛型获得具有不同返回类型的函数的返回类型?

2 个答案:

答案 0 :(得分:5)

我不妨把它放在一个答案中,虽然它看起来不会满足你的需求。 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" }),
};

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

答案 1 :(得分:0)

也许这可以解决问题。但是您需要创建一个假类。之所以有效,是因为类同时是类型和 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