Challenge 1: Write Head and Tail — Possible Solution ==================================================================== type Head = T extends [infer First, ...unknown[]] ? First : never; type Tail = T extends [unknown, ...infer Rest] ? Rest : []; // --- Usage --- type H1 = Head<[string, number, boolean]>; // string type T1 = Tail<[string, number, boolean]>; // [number, boolean] type H2 = Head<[boolean]>; // boolean type T2 = Tail<[boolean]>; // [] type H3 = Head<[]>; // never — no first element exists type T3 = Tail<[]>; // [] — nothing left to remove, base case // A quick runtime pairing to show they compose the way Curried does internally: function describeFirst(tuple: T): Head { return tuple[0] as Head; } const first = describeFirst(["a", 1, true] as [string, number, boolean]); // first: string WHY THIS WORKS -------------- - Head uses `T extends [infer First, ...unknown[]]` — the pattern only cares about capturing the first element, so the rest of the tuple is matched loosely with `...unknown[]` (any number of remaining elements of any type). - Tail uses `T extends [unknown, ...infer Rest]` — the mirror image: the first element's type doesn't matter (`unknown`), but `infer Rest` captures everything after it as a tuple. - Both types have a base case for `[]` (the empty tuple): Head<[]> falls through to `never` because there's no first element to match, and Tail<[]> falls through to `[]` because there's nothing left to remove — exactly the base case Curried relies on to eventually stop recursing when Args becomes empty.