通用函数的Typescript ReturnType

时间:2018-05-13 23:15:09

标签: typescript generics

TypeScript 2.8中的新ReturnType是一个非常实用的功能,可让您提取特定功能的返回类型。

function foo(e: number): number {
    return e;
}

type fooReturn = ReturnType<typeof foo>; // number

但是,我在泛型函数的上下文中使用它时遇到了麻烦。

function foo<T>(e: T): T {
    return e;
}

type fooReturn = ReturnType<typeof foo>; // type fooReturn = {}

type fooReturn = ReturnType<typeof foo<number>>; // syntax error

type fooReturn = ReturnType<(typeof foo)<number>>; // syntax error

有没有办法提取泛型函数给定特定类型参数的返回类型?

5 个答案:

答案 0 :(得分:10)

TypeScript编译器未将typeof foo视为泛型类型。我会说这是编译器中的一个错误。

但是,TypeScript有callable interfaces,它可以是通用的,没有任何问题,所以如果你引入一个与你的函数签名兼容的可调用接口,你可以像这样实现你自己的等效ReturnType

function foo<T>(x: T): T {
  return x;
}


interface Callable<R> {
  (...args: any[]): R;
}

type GenericReturnType<R, X> = X extends Callable<R> ? R : never;

type N = GenericReturnType<number, typeof foo>; // number

答案 1 :(得分:6)

如果要获取某些特殊的泛型类型,可以使用伪函数将其包装。

const wrapperFoo = () => foo<number>()
type Return = ReturnType<typeof wrapperFoo>

更复杂的演示

function getList<T>(): {
  list: T[],
  add: (v: T) => void,
  remove: (v: T) => void,
  // ...blahblah
}
const wrapperGetList = () => getList<number>()
type List = ReturnType<typeof wrapperGetList>
// List = {list: number[], add: (v: number) => void, remove: (v: number) => void, ...blahblah}

答案 2 :(得分:1)

如果可以更改函数定义,我发现了一种简便的方法来实现此目的。 在我的情况下,我需要将打字稿类型male_count = 0 female_count = 0 male_categories = set(['male', 'boy', 'guy', 'man']) female_categories = set(['female', 'girl', 'lady', 'woman']) for word in wordlist: if word in male_categories: male_count += 1 if word in female_categories: female_count += 1 与泛型函数一起使用,正是我在尝试counting males + boys + guy + man并有效地使它无效。因此,实现此目标的最佳方法是通过 接口函数定义 更改 函数定义 ,这也将起作用打字稿类型为Parameters

以下是OP所述情况的示例:

Parameters<typeof foo<T>>

答案 3 :(得分:0)

这是我当前正在使用的解决方案,用于提取导入库的未导出内部类型(例如knex):

// foo is an imported function that I have no control over
function foo<T>(e: T): InternalType<T> {
    return e;
}

interface Wrapper<T> {
  // wrapped has no explicit return type so we can infer it
  wrapped(e: T) {
    return foo<T>(e)
  }
}

type FooInternalType<T> = ReturnType<Wrapper<T>['wrapped']>
type Y = FooInternalType<number>
// Y === InternalType<number>

答案 4 :(得分:0)

const wrapperFoo = (process.env.NODE_ENV === 'development' ? foo<number>() : undefined)!
type Return = typeof wrapperFoo

对于 development,我什至会使用 NODE_ENV 或一些像 test 这样的随机字符串(只要 TypeScript 不抛出错误),而不是 typescript_helper它永远不会执行,因为它不会在运行时使用。