DEV Community

0ro
0ro

Posted on • Updated on • Originally published at 0ro.github.io

Infer keyword in TypeScript 📜

TypeScript's infer keyword is your secret weapon for effortlessly deducing types, simplifying code, and unlocking the full potential of type inference. In this article, we'll explore how infer can make your TypeScript development smoother and more efficient. 🚀

Type inference in TypeScript is used to provide type information when there is no explicit type annotation. This usually occurs when you haven't added types to your variables:

let str = "Hello, World!"; // str is a string here
Enter fullscreen mode Exit fullscreen mode

Everything is fine with this; TypeScript handles it for you. 👍

If you want to try type inference yourself you can use the infer keyword, and it will look like this:

let str = "Hello, World!"; // str is a string

type GetType<T> = T extends infer S ? S : never;
type T1 = GetType<typeof str>; // string
Enter fullscreen mode Exit fullscreen mode

Of course, this example may seem strange and not interesting, but it can give you an idea of how the infer keyword can be used later. 🤔

As you can see, we used infer within a conditional statement, and this is a limitation of using infer in TypeScript. Also, you cannot use it outside of an extends clause.

If you want to extract the type of an element inside an array, you can do it like this:

let arr = [1,2,3];

type GetTypeOfArrayElement<T> = T extends (infer S)[] ? S : never;

type T1 = GetTypeOfArrayElement<typeof arr>; // number
Enter fullscreen mode Exit fullscreen mode

Here, the infer keyword allows you to extract the type within the array and then use it. It's like defining a reference that you can use later.

That example, also might not seem very interesting because, in the end, you can achieve the same with this approach:

type T2 = typeof arr[0]; // number
Enter fullscreen mode Exit fullscreen mode

However, TypeScript has more complex structures that you cannot work around with simple syntax. Let's consider promises. What if you need to determine the type of the value returned by a promise? Here is where infer can also help you:

let promise = Promise.resolve([1, 2, 3]); // Promise<number[]>

type GetTypeOfPromise<T> = T extends Promise<infer S> ? S : never;

type T1 = GetTypeOfPromise<typeof promise>; // number[]
type T2 = GetTypeOfPromise<Promise<number>>; // number
type T3 = GetTypeOfPromise<Promise<string[]>>; // string[]
Enter fullscreen mode Exit fullscreen mode

By the way, Typescript itself already have a built-in utility for it that has more powerful functionality 👏:

type T4 = Awaited<typeof promise> // number[]
Enter fullscreen mode Exit fullscreen mode

Let's go further. The gaining access to function arguments can be defined like this:

type GetTypeOfFirstArgument<T> = T extends (arg: infer U, ...args) => any ? U : never;

type T1 = GetTypeOfFirstArgument<typeof document.getElementById>; // string
type T2 = GetTypeOfFirstArgument<(arg1: string, arg2: number) => void >; // string
Enter fullscreen mode Exit fullscreen mode

And in the end, maybe the most practical example with React component function.

It can happen that in some libraries, they didn't export the props for their component. But in your code, you really need it. So with infer keyword getting the prop type is possible, and will look like this:

const OutsideComponent: React.FC<{ name: string }> = () => null;

type InferProps<T> = T extends React.FC<infer P> ? P : never;

type Props = InferProps<typeof OutsideComponent>;
Enter fullscreen mode Exit fullscreen mode

This technique allows you to infer the prop types of a React component function even if they aren't explicitly exported

Conclusion

Incorporating infer into your TypeScript toolkit can significantly streamline your code, simplify complex type manipulations, and boost your development productivity. Embrace this powerful keyword to unlock the true potential of type inference in TypeScript. Happy coding! 🚀

Top comments (0)