Inside a conditional’s matching branch, infer names a type the checker can extract from a pattern. T extends readonly (infer Item)[] ? Item : never asks whether T is an array and, if so, captures its element type as Item. Infer is not a runtime variable or a validation step.
Use parentheses around infer Item in this array pattern so it is easy to read: first identify the array, then its element. A mutable array also fits the readonly array pattern. The fallback never says this helper intentionally has no result for a non-array input.
The same idea underlies standard helpers such as ReturnType for functions and Awaited for asynchronous results. Prefer built-in helpers rather than writing a recursive promise unwrapper from memory. Today we use one small array extractor so you can read a library declaration with confidence.
Deriving a type avoids two annotations drifting apart, but it also couples the consumer to the source shape. Name a stable public contract when you want to control changes. Do not reach for a complex type puzzle when an explicit parameter is clearer.
Predict, check, and run
Write the output before running. Use Check types first, then Check & run. Types disappear at runtime: explain both what the compiler checks and what the code actually does. Each editor is an independent ES module; await asynchronous work explicitly.
type ItemOf<T> = T extends readonly (infer Item)[] ? Item : never;
const title: ItemOf<readonly string[]> = "Types";
const pages: ItemOf<number[]> = 120;
console.log(title, pages);Enable JavaScript to edit and type-check this example.
Check your prediction
Types 120 Read the compiler error
Predict the rejected relationship before checking. Read the real diagnostic and its source location; fix the contract or the value instead of hiding it with an assertion.
type ItemOf<T> = T extends readonly (infer Item)[] ? Item : never;
const title: ItemOf<string[]> = 25;
console.log(title);Enable JavaScript to edit and type-check this example.
Check your diagnosis
Item is string for string[]. Inferring a type does not convert the assigned number into text.
Build it yourself
infer & Derived Types: practise
Write ValueOfBox<T> that extracts V from {value: V}, otherwise never. Declare a numeric extracted value, print 25, and explain what happens for a record without value.
// Start from the stated contract. Add a valid call and an edge case.Enable JavaScript to edit and type-check this example.
Hint 1: the idea
Put infer in the property pattern, not in the type parameter list.
Hint 2: a first step
The successful branch can return the captured type name.
Show one solution
type ValueOfBox<T> = T extends { value: infer V } ? V : never;
const pages: ValueOfBox<{ value: number }> = 25;
console.log(pages);Enable JavaScript to edit and type-check this example.
25Trace the implementation against the task before comparing styles. A passing example supports that case; use the changes below to challenge the wider contract.
Read ReturnType before using it
ReturnType<F> is a built-in helper that extracts a function’s declared or inferred return type. Pass a function type, not a call result. In ReturnType<typeof makeBook>, typeof is the type query from intermediate; it does not invoke makeBook. This example is synchronous. Day 5 adds Awaited for promises.
function makeBook() {
return { title: "Types", pages: 120 };
}
type Book = ReturnType<typeof makeBook>;
const book: Book = makeBook();
console.log(book.title, book.pages);Enable JavaScript to edit and type-check this example.
Check your prediction
Types 120 Change it and test it
Try {value:string}|{value:number} and predict the extracted union. Then use ReturnType<typeof aFunction> on a small function and compare the result to a handwritten alias.
Completion is saved in this browser only. It does not measure mastery.