Bird
Raised Fist0
Typescriptprogramming~10 mins

Inferring types with infer keyword in Typescript - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Inferring types with infer keyword
Start with conditional type
↓
Check if type matches pattern with infer
Yes | No↓
Return fallback type
↓
Extract inferred type
↓
Use inferred type in result
The infer keyword extracts a type from a pattern inside a conditional type, allowing us to capture and reuse parts of a type.
Execution Sample
Typescript
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

// Example function type
type Fn = (x: number) => string;

// Infer return type
type Result = GetReturnType<Fn>;
This code extracts the return type of a function type using infer inside a conditional type.
Execution Table
StepActionEvaluationResult
1Check if Fn matches (...args: any[]) => infer RFn is (x: number) => stringMatches pattern, infer R = string
2Extract inferred type RR = stringR = string
3Return inferred type RResult = stringResult = string
4If no match, return neverNot applicable hereN/A
💡 Type Fn matches the function pattern, so inferred type R is string and returned.
Variable Tracker
VariableStartAfter Step 1After Step 2Final
TFn = (x: number) => stringMatches patternN/AN/A
RundefinedInferred as stringstringstring
ResultundefinedN/AN/Astring
Key Moments - 3 Insights
Why do we use 'infer R' inside the conditional type?
Because 'infer R' lets TypeScript capture the return type part of the function type T, as shown in execution_table step 1 and 2.
What happens if the type T does not match the function pattern?
The conditional type returns 'never' as fallback, shown in execution_table step 4.
Is the inferred type 'R' available outside the conditional type?
No, 'R' only exists inside the conditional type scope to extract and return the type, as seen in variable_tracker.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the inferred type 'R' after step 2?
Anumber
Bstring
Cnever
Dunknown
💡 Hint
Check the 'Evaluation' and 'Result' columns in execution_table row 2.
At which step does the conditional type return 'never'?
AStep 1
BStep 3
CStep 4
DStep 2
💡 Hint
Look at the 'exit_note' and execution_table row 4.
If the function type changed to (x: number) => boolean, what would be the final Result type?
Aboolean
Bnever
Cstring
Dany
💡 Hint
Refer to how 'R' is inferred from the return type in execution_table step 1 and 2.
Concept Snapshot
Syntax: type NewType<T> = T extends Pattern<infer R> ? R : Fallback;

- 'infer' extracts a type part inside conditional types.
- Used to capture types like return types, argument types.
- If no match, fallback type is used.
- Helps create flexible, reusable type utilities.
Full Transcript
This visual trace shows how TypeScript's 'infer' keyword works inside conditional types. We start by checking if a type T matches a pattern that includes 'infer R'. If it matches, TypeScript extracts the type part as R. For example, given a function type, it extracts the return type. If it doesn't match, it returns a fallback type like 'never'. The execution table walks through these steps, showing how the inferred type R is captured and returned. The variable tracker shows how T, R, and the final Result change during the process. Key moments clarify why 'infer' is used, what happens if no match occurs, and the scope of the inferred type. The quiz tests understanding of these steps and outcomes. This helps beginners see how 'infer' extracts types dynamically in TypeScript.

Practice

(1/5)
1. What does the infer keyword do in TypeScript conditional types?
easy
A. It declares a new variable inside a function.
B. It allows TypeScript to guess and extract a type inside a conditional type.
C. It creates a new interface automatically.
D. It imports types from external modules.

Solution

  1. Step 1: Understand the role of infer

    The infer keyword is used inside conditional types to let TypeScript guess a type variable from a given type.
  2. Step 2: Identify what infer extracts

    It extracts parts of complex types, like the return type of a function or the element type of an array.
  3. Final Answer:

    It allows TypeScript to guess and extract a type inside a conditional type. -> Option B
  4. Quick Check:

    infer extracts types = A [OK]
Hint: Remember: infer extracts types inside conditional types [OK]
Common Mistakes:
  • Thinking infer declares variables in functions
  • Confusing infer with interface creation
  • Assuming infer imports types
2. Which of the following is the correct syntax to infer the return type of a function type F using infer?
easy
A. type ReturnType<F> = F extends (...args: any[]) => infer R ? R : never;
B. type ReturnType<F> = infer R extends F ? R : never;
C. type ReturnType<F> = F extends infer R => any ? R : never;
D. type ReturnType<F> = F extends (...args: infer R) => any ? R : never;

Solution

  1. Step 1: Analyze the conditional type structure

    The correct syntax uses F extends (...args: any[]) => infer R to extract the return type R.
  2. Step 2: Check each option for correct infer usage

    type ReturnType<F> = F extends (...args: any[]) => infer R ? R : never; correctly places infer R after the arrow function parameters and before the return type.
  3. Final Answer:

    type ReturnType<F> = F extends (...args: any[]) => infer R ? R : never; -> Option A
  4. Quick Check:

    Correct infer syntax for return type = A [OK]
Hint: Look for infer R right after function args in extends [OK]
Common Mistakes:
  • Placing infer outside the extends clause
  • Using infer on the wrong part of the function type
  • Confusing parameter inference with return type inference
3. Given the following code, what is the type of ElementType?
type ElementType<T> = T extends (infer U)[] ? U : T;
type Result = ElementType;
medium
A. string
B. unknown
C. never
D. string[]

Solution

  1. Step 1: Understand the conditional type with infer

    The type checks if T extends an array of some type U. If yes, it extracts U.
  2. Step 2: Apply the type to string[]

    Since string[] extends (infer U)[], U is string. So, ElementType<string[]> is string.
  3. Final Answer:

    string -> Option A
  4. Quick Check:

    Extracted element type = string [OK]
Hint: infer extracts array element type inside conditional [OK]
Common Mistakes:
  • Confusing the whole array type with element type
  • Assuming infer returns the original type
  • Ignoring the conditional fallback
4. Identify the error in this type definition that tries to infer the argument type of a function:
type ArgType<T> = T extends (arg: infer A) => void ? A : never;
type Test = ArgType<() => number>;
medium
A. The conditional type should check for return type, not argument type.
B. The syntax of infer is incorrect; it should be outside the parentheses.
C. The function type has no arguments, so infer fails and returns never.
D. The type alias is missing a generic constraint.

Solution

  1. Step 1: Analyze the function type used

    The function type () => number has no arguments.
  2. Step 2: Understand infer behavior with no matching argument

    The conditional type tries to infer argument A, but since there is no argument, the condition fails and returns never.
  3. Final Answer:

    The function type has no arguments, so infer fails and returns never. -> Option C
  4. Quick Check:

    Infer fails with no matching argument = C [OK]
Hint: Check if function actually has arguments before inferring [OK]
Common Mistakes:
  • Assuming infer always succeeds
  • Misplacing infer keyword syntax
  • Confusing argument and return type inference
5. You want to create a type Flatten<T> that extracts the element type from nested arrays using infer. For example, Flatten<number[][]> should be number[]. Which of the following correctly implements this?
hard
A. type Flatten<T> = T extends (infer U)[] ? U[] : T;
B. type Flatten<T> = T extends (infer U)[] ? Flatten : T;
C. type Flatten<T> = T extends any[] ? Flatten : T;
D. type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T;

Solution

  1. Step 1: Understand the goal of Flatten

    We want to recursively unwrap nested arrays until we reach a non-array element, then wrap it back as a single array.
  2. Step 2: Analyze type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T;'s recursive conditional

    type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T; checks if T is an array of U. If U is itself an array, it recursively calls Flatten<U>. Otherwise, it returns U[]. This matches the requirement.
  3. Final Answer:

    type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T; -> Option D
  4. Quick Check:

    Recursive infer for nested arrays = B [OK]
Hint: Use recursive conditional with infer to unwrap nested arrays [OK]
Common Mistakes:
  • Not handling recursion for nested arrays
  • Returning wrong type shape after unwrapping
  • Misplacing infer or conditional checks
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard