The infer keyword captures part of a type inside a conditional type.

infer `T extends Array<infer U> ? U : T` asks TypeScript to infer the item type when `T` is an array.

Inferred Array Item

useList
array_item.ts
Replay: real traced execution (multi-file project)
type ItemOf<T> = T extends Array<infer U> ? U : T;

function firstItem<T>(input: T | T[]): ItemOf<T[]> {
    const list: T[] = Array.isArray(input) ? input : [input];
    return list[0] as ItemOf<T[]>;
}

const useList: boolean = true;
const input: string | string[] = useList ? ["red", "blue"] : "green";
const item: string = firstItem(input);

console.log(`item=${item}`);
type ItemOf<T> = T extends Array<infer U> ? U : T;

function firstItem<T>(input: T | T[]): ItemOf<T[]> {
    const list: T[] = Array.isArray(input) ? input : [input];
    return list[0] as ItemOf<T[]>;
}

const useList: boolean = false;
const input: string | string[] = useList ? ["red", "blue"] : "green";
const item: string = firstItem(input);

console.log(`item=${item}`);
  1. useList ← true, input ← red,blue

    5    return list[0] as ItemOf<T[]>;6}78const useList→ true: boolean = true;  //@useList=false9const input→ red,blue: string | string[] = useListtrue ? ["red", "blue"] : "green";10const item: string = firstItem(inputred,blue);
  2. list ← red,blue

    1type ItemOf<T> = T extends Array<infer U> ? U : T;23function firstItem<T>(inputred,blue: T | T[]): ItemOf<T[]> {4    const list→ red,blue: T[] = Array.isArray(inputred,blue) ? inputred,blue : [input];5    return list[0]red as ItemOf<T[]>;6}
  3. item ← red

    8const useList: boolean = true;  //@useList=false9const input: string | string[] = useList ? ["red", "blue"] : "green";10const item→ red: string = firstItem(inputred,blue);1112console.log(`item=${itemred}`);
    outputitem=red
  1. useList ← false, input ← green

    5    return list[0] as ItemOf<T[]>;6}78const useList→ false: boolean = false;9const input→ green: string | string[] = useListfalse ? ["red", "blue"] : "green";10const item: string = firstItem(inputgreen);
  2. list ← green

    1type ItemOf<T> = T extends Array<infer U> ? U : T;23function firstItem<T>(inputgreen: T | T[]): ItemOf<T[]> {4    const list→ green: T[] = Array.isArray(inputgreen) ? inputgreen : [input];5    return list[0]green as ItemOf<T[]>;6}
  3. item ← green

    8const useList: boolean = false;9const input: string | string[] = useList ? ["red", "blue"] : "green";10const item→ green: string = firstItem(inputgreen);1112console.log(`item=${itemgreen}`);
    outputitem=green