Explosion Pills
Explosion Pills

Reputation: 191809

Simplify ReturnType for union of multiple functions from an object

I have an object of functions, and I need to create a type that is the union of what they return. A simple example:

const actions = {
  success: () => true,
  count: () => 0,
};

Now, I want to create the corresponding type. This can be done via:

type AvailableValues = ReturnType<typeof actions.success | typeof actions.failure>;

This works, but it's very verbose -- chiefly having to write typeof actions repeatedly.

Pick<typeof actions, 'success' | 'failure'> is close, but the type it generates is an object rather than the union of function return types, so I'm sort of back to where I started.

Is there any way to extract multiple return types simultaneously?

See a setup example here: https://www.typescriptlang.org/play?#code/MYewdgzgLgBAhsKBLcEYF4YG8BQMYQCuwwAphBAFwwAUAlBgHwxQBOhpANHjKIWFGr0mMAAzcAvgG4cOKAE8ADqRgBBAG5wkAGzgAjbaQBqcbRzSYASqSiFWYACpLSAHgXKQAM3iIUkAHREJORoAD4szl4+yKj+fAKMUkA

Upvotes: 0

Views: 280

Answers (2)

kaarelss
kaarelss

Reputation: 1

This worked for me.

type Actions = typeof actions;

type AvailableValues = ReturnType<Actions[keyof Actions]>

Upvotes: 0

jcalz
jcalz

Reputation: 330216

If actions had some non-functions in there or if you need to manually specify "success" and "count" for some reason (maybe there are other functions that you don't want the return types of), then you can do this by using a lookup type to get the function types at the "success" and "count" keys, like this:

type AvailableValues = ReturnType<(typeof actions)['success' | 'count']>

A lookup type is the bracket notation where given a type T and a key type K (or a union of keys) then the property type at that key (or union of property types at those keys) is T[K].


If you want to get a union of the return types for all function-valued properties of an object type in general, you can write it like this:

type ReturnTypesOfFunctionProps<T> = {
  [K in keyof T]: T[K] extends (...args: any) => infer R ? R : never
}[keyof T];

Note that T[K] extends (...args: any) => infer R ? R : never is using conditional type inference and is basically the same as ReturnType<T[K]> (see library definition) except that ReturnType constrains its input.

And then for your type it yields the same thing:

type AvailableValues2 = ReturnTypesOfFunctionProps<typeof actions>;
// type AvailableValues2 = number | boolean

Playground link to code

Upvotes: 2

Related Questions