Infer in TypeScript: Automatic Type Inference for Powerful Typing

In this blog, we are going to learn Infer in Typescript with some fancy examples. Like change Type types, recursive types …
What is infer in Typescript?
In Typescript, Infer is just a keyword used within conditional types to infer or learn types based on other types. It allows TypeScript to automatically deduce the types of variables or parameters based on their usage within the code.
Infer is always used with conditional type so it should be used with the extends keyword.
Find the return type of any function
type ReturnFuncType<T> = (...args: any) => T extends infer R ? R : never
const foo = () => 2
type Foo = ReturnFuncType<typeof foo>
// type Foo = (...args: any) => () => number
ReturnFuncType< T >: it is taking any function as an argument then it try to infer the return type of the function via this condition:
T extends `${infer R}${infer K}` ? `${ReverseType<K>}${R}` : T
Then we can find the return type of the functions.
type ReverseType<T> =
T extends`${infer R}${infer K}` ? `${ReverseType<K>}${R}` : T
type test1 = ReverseType<'1234'> // test1:'1234'
type test2 = ReverseType<'typescript-guru'> // test2:'urug-tpircsepyt'
type test3 = ReverseType<'1_2_3'> // test3:'3_2_1'
ReverseType< T >: infer the first character then put it to last. then it continues to do it till reaches the end of the given type via this condition:
T extends `${infer R}${infer K}` ? `${ReverseType<K>}${R}` : T
Remove number from string
type numbers = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0'
type RemoveNumber<T> = T extends numbers ? never : T
type RemoveNumberFromString<T> =
T extends `${infer R}${infer K}` ?
R extends numbers ?
`${RemoveNumberFromString<K>}` : `${R}${RemoveNumberFromString<K>}`
: RemoveNumber<T>
type test1 = RemoveNumberFromString<'test'> // test1:'test'
type test2 = RemoveNumberFromString<'1234'> // test2:''
type test3 = RemoveNumberFromString<'123test123'> // test3:'test'
type test4 = RemoveNumberFromString<'1t2e3s4t'> // test4:'test'
RemoveNumberFromString< T >: This type is checked character by character if it is extended by number or not. If it is extended by a number, it is removed from the string via this condition:
T extends`${infer R}${infer K}` ?
R extends numbers ?
`${RemoveNumberFromString<K>}` : `${R}${RemoveNumberFromString<K>}`
: RemoveNumber<T>
This condition might look complex but we can think of a recursive function like other programming languages. The most important thing is the base case for this type.
Convert Kebab-case to Snake_case
type Kebab2Snake<T> =
T extends`${infer R}-${infer K}` ? `${R}_${Kebab2Snake<K>}` : T
type test1 = Kebab2Snake<'test-1'> // test1:'test_1'
type test2 = Kebab2Snake<'test-2'> // test2:'test_2'
type test3 = Kebab2Snake<'kebab-case'> // test3:'kebab_case'
Kebab2Snake< T >: This type finds the ‘…-…’ this pattern (that represents Kebab-case) and replaces it with ‘…_…’ via this condition:
T extends `${infer R}-${infer K}` ? `${R}_${Kebab2Snake<K>}` : T
Summary
Infer should be used with conditional types. (extends).
We can use infer to find and infer a type that we don’t know.
We can create a recursive operation by using infer.
Back