function identity<T>(value: T): T {
return value;
}Generics let a function preserve type information across inputs and outputs.
Advanced type operators, mapped types, conditional types, and utility types.
Reusable type parameters for functions, interfaces, and classes.
function identity<T>(value: T): T {
return value;
}Generics let a function preserve type information across inputs and outputs.
function first<T>(items: T[]): T | undefined {
return items[0];
}A generic function can infer `T` from the array argument.
interface ApiResponse<T> {
data: T;
error?: string;
}Generic interfaces are ideal for API wrappers and paginated result types.
function printLength<T extends { length: number }>(value: T) {
console.log(value.length);
}Constraints allow generic code to safely access known members.
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}This is one of the most useful generic patterns in application code.
`keyof`, `typeof`, indexed access, and type queries.
type User = { id: number; name: string };
type UserKeys = keyof User; // "id" | "name"`keyof` is foundational for many advanced type helpers.
const config = {
retries: 3,
cache: true,
};
type Config = typeof config;`typeof` in a type position is useful when a runtime object already defines the shape.
type User = { profile: { email: string } };
type Email = User["profile"]["email"];Indexed access types help avoid repeating nested object types manually.
type Method = "GET" | "POST";
type Route = "/users" | "/posts";
type Endpoint = `${Method} ${Route}`;Template literal types are powerful for modeling event names, API routes, and CSS tokens.
Transform one type into another with reusable helpers.
type Flags<T> = {
[K in keyof T]: boolean;
};Mapped types let you derive new object types from existing ones.
type IsString<T> = T extends string ? true : false;Conditional types are the basis for many advanced utility helpers.
type GetReturn<T> = T extends (...args: never[]) => infer R ? R : never;`infer` captures a type from a matched pattern in a conditional type.
type Success = { kind: "success"; data: string };
type Failure = { kind: "error"; message: string };
type Result = Success | Failure;Discriminated unions pair especially well with narrowing in control flow.
Built-in helpers like Partial, Pick, Record, and Awaited.
type User = { id: number; name: string; email: string };
type UserPatch = Partial<User>;Useful for patch/update payloads and intermediate object construction.
type User = { id?: number; name?: string };
type CompleteUser = Required<User>;Useful when optional data must be normalized before use.
type User = { id: number; name: string; email: string };
type PublicUser = Pick<User, "id" | "name">;Useful for API DTOs and lightweight derived shapes.
type User = { id: number; passwordHash: string; email: string };
type SafeUser = Omit<User, "passwordHash">;A common pattern for removing internal or sensitive fields.
type FeatureFlag = "billing" | "search";
const flags: Record<FeatureFlag, boolean> = {
billing: true,
search: false,
};`Record` is often cleaner than a custom index signature.
type Result = Awaited<Promise<Promise<string>>>; // string`Awaited` models how `await` recursively unwraps promises.
function createUser() {
return { id: 1, name: "Ada" };
}
type User = ReturnType<typeof createUser>;Useful when you want a type that stays synced with a function implementation.