TypeScript Mapped Types with Utility Types

Learn how mapped types and utility types work together. Examples for creating custom transformations using keyof, in, and conditional types.

Advanced Patterns

Detailed Explanation

Mapped Types + Utility Types

Mapped types iterate over the keys of a type and transform each property. Combined with utility types, they enable powerful custom transformations.

Basic Mapped Type

type Nullable<T> = {
  [K in keyof T]: T[K] | null;
};

interface User {
  name: string;
  age: number;
}

type NullableUser = Nullable<User>;
// { name: string | null; age: number | null }

Key Remapping (TypeScript 4.1+)

type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }

Filtering Keys with Exclude

type PublicKeys<T> = {
  [K in keyof T as K extends `_${string}` ? never : K]: T[K];
};

interface Service {
  getData(): string;
  _internal(): void;
  _cache: Map<string, unknown>;
  name: string;
}

type PublicService = PublicKeys<Service>;
// { getData(): string; name: string }

Conditional Property Types

type ReadonlyArrays<T> = {
  [K in keyof T]: T[K] extends any[] ? readonly T[K][number][] : T[K];
};

interface State {
  items: string[];
  count: number;
  tags: number[];
}

type ImmutableState = ReadonlyArrays<State>;
// { items: readonly string[]; count: number; tags: readonly number[] }

Building Custom Utility Types

// Make specific keys optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

// Make specific keys required
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

// Make specific keys readonly
type ReadonlyBy<T, K extends keyof T> = Omit<T, K> & Readonly<Pick<T, K>>;

Use Case

Use mapped types with utility types when the built-in utilities are not enough and you need custom property transformations. Common for building reusable type utilities in shared libraries, form libraries, state management tools, and API clients.

Try It — TypeScript Utility Types

Open full tool