Concept 2 of 12
Generic parameters
A generic parameter turns an alias into a function that takes types and returns a type. Once you read it that way — arguments in, type out — the rest of the type system stops looking like syntax and starts looking like programming.
Parameters, defaults and all
type Box<T> = { value: T } type Boxed = Box<string> // { value: string } // Defaults work exactly like function parameter defaults. type List<T, Sep extends string = ','> = { items: T[]; sep: Sep } type Plain = List<number> // sep is ','
Type parameters are positional, can have defaults, and the defaults may reference earlier parameters. Recursive type-level code leans on this constantly: an accumulator is nearly always a defaulted parameter the caller never passes.
`extends` here means "must be at least"
type Length<S extends string> = S['length'] Length<'abc'> // ok Length<42> // Error: 42 does not satisfy the constraint 'string'
In a parameter list, `extends` is a constraint: it restricts what may be passed. It is not inheritance, and it does not mean the parameter *is* that type — only that whatever arrives is assignable to it.
The same keyword means something completely different inside a conditional type, where it asks a question rather than imposing a rule. Telling the two apart by position is one of the genuine hurdles in learning this.
The common wrong answer
// Intent: accept any object and read a key from it. type Get<T, K> = T[K] // ^ Error: type K cannot be used to index type T // Fixed: constrain K to the keys T actually has. type Get2<T, K extends keyof T> = T[K]
Without a constraint the compiler has no reason to believe `K` is a valid key, so it refuses. Constraints are not decoration — they are what lets the body of a generic type do anything with its parameters.
Takeaway
Read `type F<A, B> = ...` as a function from types to types. `extends` in the parameter list is the argument check at the door.