TypeScript Conditional Types
A conditional type chooses a type based on an assignability relationship. infer can capture part of a matched type, such as an array’s element or a function’s result.
How it works
ElementOrSelf extracts an array element and leaves a non-array type unchanged. This makes a small normalization contract reusable without enumerating every element type. Conditional types involving a naked type parameter distribute over union members; wrapping both sides in tuples changes that behavior when the whole union should be considered together. These rules describe types, not runtime if statements.
Run the code
Try in playground loads this source without running it. Choose Run when ready. The existing TypeScript 5.8.3 worker transpiles and executes one file; it does not perform full semantic type checking, load npm imports or provide DOM/Node APIs. Use the local compiler for the type contract.
For a full check, save the three downloads together in a new folder, run npm install, then npm run check. Use npm run build followed by npm start to execute the checked JavaScript with Node. The supplied project enables strict checking, indexed-access checks and exact optional properties.
Example
type ElementOrSelf<T> = T extends readonly (infer Item)[] ? Item : T;
type Label = ElementOrSelf<readonly string[]>;
type Count = ElementOrSelf<number>;
const label: Label = "Bean";
const count: Count = 4;
console.log(label, count);
Expected result
Bean 4
The two aliases resolve to string and number. The companion rejection fixture confirms that a boolean cannot be assigned to the extracted string type. Start with small named transformations and inspect the result; deeply recursive conditional types can slow checking and produce unhelpful error messages.