Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export return type of function in Typescript

Tags:

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; }
like image 445
user3711864 Avatar asked Dec 20 '16 21:12

user3711864


1 Answers

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.

like image 87
artem Avatar answered Sep 22 '22 14:09

artem