user3711864
user3711864

Reputation: 359

Export return type of function in Typescript

I have a function that builds an object, like this:

function toast() {
  return {
    a: "a",
    b: "b"
  }
}

I can define the type of the function as

type ToastFunctionType = typeof toast

This type would be

() => { a: string; b: string; }

However, I only want the type of the return value. Is it possible to extract the type of the return value of toast? In my use case, the actual values of the objects are using pretty verbose generic type arguments. Type inference gets them just right and I would like to avoid maintaining a very verbose interface (that I need to export).

What I want in the case of toast is just

{ a: string; b: string; }

Upvotes: 14

Views: 11481

Answers (1)

artem
artem

Reputation: 51579

Yes it's possible. The trick is to have some value somewhere which is declared with the type you need (return type of toast()), without actually calling toast(). You can do that by introducing another function that returns a value of appropriate type (the actual value is null), then creating a variable and assigning it the value returned by that function, then getting typeof of that.

I could not find a way without adding unused variable, but since the variable is initialized by null that's immediately returned from the function, I suppose that runtime overhead is negligible. Here is the code:

function toast() {
  return {
    a: "a",
    b: "b"
  }
}

function getReturnType<R> (f: (...args: any[]) => R): {returnType: R} {
    return null!;
}

// dummy variable, used for retrieving toast return type only
let toastType = getReturnType(toast);

export type ToastReturnType = typeof toastType.returnType;

UPDATE Feb 2018

In the upcoming 2.8 release, there are some new language features that make it possible without involving dummy variables and functions.

This example compiles with typescript@next:

export function z() {
    return {a: 1, b: '2'}
}

export function v() {
}

type ReturnType<T extends (...args: any[]) => any> = 
    T extends (...args: any[]) => infer R ? R : never;

export type RZ = ReturnType<typeof z>; // { a: number; b: string; }
export type RV = ReturnType<typeof v>; // void

TypeScript >= 2.8

As of version 2.8, TypeScript has a built-in generic ReturnType that you can use.

Upvotes: 21

Related Questions