TypeScript Types and Generics

Advanced type operators, mapped types, conditional types, and utility types.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

Generics

Reusable type parameters for functions, interfaces, and classes.

Generic identity function

Use a type parameter for reusable function typing.

typescriptANYtypescriptgenericsfunctions
typescript
function identity<T>(value: T): T {
  return value;
}

Generics let a function preserve type information across inputs and outputs.

Generic array helper

Write array helpers that preserve element types.

typescriptANYtypescriptgenericsarrays
typescript
function first<T>(items: T[]): T | undefined {
  return items[0];
}

A generic function can infer `T` from the array argument.

Generic interface

Parameterize a reusable interface.

typescriptANYtypescriptgenericsinterface
typescript
interface ApiResponse<T> {
  data: T;
  error?: string;
}

Generic interfaces are ideal for API wrappers and paginated result types.

Constrain generic types

Require a minimum shape for a type parameter.

typescriptANYtypescriptgenericsconstraints
typescript
function printLength<T extends { length: number }>(value: T) {
  console.log(value.length);
}

Constraints allow generic code to safely access known members.

Constrain a key parameter with `keyof`

Accept only valid property names for a given object type.

typescriptANYtypescriptgenericskeyofindexed-access
typescript
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.

Type Operators

`keyof`, `typeof`, indexed access, and type queries.

Use `keyof`

Get a union of property names from a type.

typescriptANYtypescriptkeyof
typescript
type User = { id: number; name: string };
type UserKeys = keyof User; // "id" | "name"

`keyof` is foundational for many advanced type helpers.

Use `typeof` in types

Infer a type from an existing value.

typescriptANYtypescripttypeof
typescript
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.

Use indexed access types

Get a nested property type from another type.

typescriptANYtypescriptindexed-access
typescript
type User = { profile: { email: string } };
type Email = User["profile"]["email"];

Indexed access types help avoid repeating nested object types manually.

Use template literal types

Compose string literal types from smaller pieces.

typescriptANYtypescripttemplate-literal-types
typescript
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.

Mapped and Conditional Types

Transform one type into another with reusable helpers.

Simple mapped type

Create a type by iterating over keys.

typescriptANYtypescriptmapped-types
typescript
type Flags<T> = {
  [K in keyof T]: boolean;
};

Mapped types let you derive new object types from existing ones.

Conditional type

Choose a type based on another type relationship.

typescriptANYtypescriptconditional-types
typescript
type IsString<T> = T extends string ? true : false;

Conditional types are the basis for many advanced utility helpers.

Infer a return type

Use `infer` inside a conditional type.

typescriptANYtypescriptconditional-typesinfer
typescript
type GetReturn<T> = T extends (...args: never[]) => infer R ? R : never;

`infer` captures a type from a matched pattern in a conditional type.

Discriminated union pattern

Model variant objects with a shared discriminant field.

typescriptANYtypescriptdiscriminated-unions
typescript
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.

Utility Types

Built-in helpers like Partial, Pick, Record, and Awaited.

Use `Partial<T>`

Make every property optional.

typescriptANYtypescriptutility-typespartial
typescript
type User = { id: number; name: string; email: string };
type UserPatch = Partial<User>;

Useful for patch/update payloads and intermediate object construction.

Use `Required<T>`

Make all properties required.

typescriptANYtypescriptutility-typesrequired
typescript
type User = { id?: number; name?: string };
type CompleteUser = Required<User>;

Useful when optional data must be normalized before use.

Use `Pick<T, K>`

Select a subset of properties.

typescriptANYtypescriptutility-typespick
typescript
type User = { id: number; name: string; email: string };
type PublicUser = Pick<User, "id" | "name">;

Useful for API DTOs and lightweight derived shapes.

Use `Omit<T, K>`

Remove properties from a type.

typescriptANYtypescriptutility-typesomit
typescript
type User = { id: number; passwordHash: string; email: string };
type SafeUser = Omit<User, "passwordHash">;

A common pattern for removing internal or sensitive fields.

Use `Record<K, T>`

Type objects whose keys all map to the same value type.

typescriptANYtypescriptutility-typesrecord
typescript
type FeatureFlag = "billing" | "search";
const flags: Record<FeatureFlag, boolean> = {
  billing: true,
  search: false,
};

`Record` is often cleaner than a custom index signature.

Use `Awaited<T>`

Unwrap the resolved type of a promise-like value.

typescriptANYtypescriptutility-typesawaited
typescript
type Result = Awaited<Promise<Promise<string>>>; // string

`Awaited` models how `await` recursively unwraps promises.

Use `ReturnType<T>`

Extract a function’s return type.

typescriptANYtypescriptutility-typesreturntype
typescript
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.

Recommended next

No recommendations yet.