Quick Overview
An unconstrained `T` could be anything, so the compiler blocks every property access on it. `T extends { id: string }` promises the shape, restoring access while still accepting any type that satisfies it.
By default, a generic type parameter <T> can be absolutely anything (number, string, object, array). But what if your function needs to access a specific property (like .length or .id) on T?
extends Constraint KeywordUse Generic Constraints (<T extends Requirement>) to constrain generic parameters so they must satisfy a specific interface or type shape:
interface HasLength {
length: number;
}
// T is constrained to types that have a numeric '.length' property
function logLength<T extends HasLength>(item: T): T {
console.log(`Length is: ${item.length}`);
return item;
}
logLength("Hello World"); // Valid! (strings have .length)
logLength([1, 2, 3, 4]); // Valid! (arrays have .length)
logLength({ length: 10 });// Valid!
// logLength(12345); // Error: Type 'number' does not have a '.length' property!
keyofEnsure a property key exists on an object parameter using <K extends keyof T>:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 101, name: "Alex", isOnline: true };
const nameValue = getProperty(user, "name"); // Type: string
const idValue = getProperty(user, "id"); // Type: number
// getProperty(user, "invalidKey"); // Error: Argument of type '"invalidKey"' is not assignable to "id" | "name" | "isOnline"
<T extends Shape>, extends means "T is assignable to Shape", NOT class inheritance!Constrain generic parameters when accessing properties. Next, let's explore Discriminated Unions and Pattern Matching!
TypeScript erases entirely at build time, so a `string` annotation produces no runtime check whatsoever. A value arriving from an API is whatever the server actually sent, regardless of what the annotation claims.
`let x = "GET"` infers `string` because the binding can change; `const x = "GET"` infers the literal `"GET"`. That widening rule is why object properties need `as const` to stay narrow.
`string[]` is any number of strings; `[string, number]` is exactly two, in that order. `readonly` removes the mutating methods at compile time, so `push` becomes a type error rather than a runtime surprise.