DEV Community

Nicholas Kircher
Nicholas Kircher

Posted on

How 2 TypeScript: Serious business with TypeScript's infer keyword.

Hey you! Do you want to get the return type of a function and use it, without knowing what it really is, or asking the user of your thing to supply it outright?

Of course you do.

type GetReturnType<original extends Function> = 
  original extends (...x: any[]) => infer returnType ? returnType : never
Enter fullscreen mode Exit fullscreen mode

Conditional types in typescript allow you to introduce type variables into the expression in a rather dynamic way. Notice the infer keyword. That says to TypeScript: "I want to take whatever TypeScript infers to be at this position and assign it to the name returnType". It just so happens that the thing at that position is the return type of a given function, that we have called original.

What happens when you put it into action? I AM SO GLAD YOU ASKED! Take this extremely powerful, useful, and all-round fantasmical Higher Order Function

const someRandomStuff = <fn extends Function>(originalFn: fn) => {
  const result: GetReturnType<fn> = originalFn(12345);

  return result;
Enter fullscreen mode Exit fullscreen mode

The type of result is going to be whatever the return type of originalFn(12345) is. We don't actually know, until...

const innerFn = (item: number) => item.toString();
Enter fullscreen mode Exit fullscreen mode

FYI, TS will infer the output of innerFn to be a string. Then...

const output = someRandomStuff(innerFn); // ALL SYSTEMS GO
Enter fullscreen mode Exit fullscreen mode

Would you like to play a game? What is the type of output? The answer is: What is the type of innerFn?

It's a string!

If it weren't for this trick, the type of output would be any. I know, I was surprised too. But it's true.

You can do the same sort of thing with anything that TypeScript can infer. Wanna get the type of arguments?

type NYET = never // preparation for unfunny joke
type GetArgumentType<original extends Function> =
  original extends (...x: infer argumentsType) => any ? argumentsType : NYET
Enter fullscreen mode Exit fullscreen mode

That's all, see you next time.

Top comments (1)

yi profile image

I guess it's worth mentioning there is built in type ReturnType<fn> which can be used to infer the return type of any given function.