codez.guru

Built-in Utility Types

TypeScript provides several built-in utility types that let you transform, manipulate, and reuse existing types in a powerful way.


Partial<t>

Makes all properties in a type optional:

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

type UpdateUser = Partial<user>;
// { id?: number; name?: string }

Required<t>

Makes all optional properties required:

type User = {
  id?: number;
  name?: string;
};

type FullUser = Required<user>; // { id: number; name: string }

Readonly<t>

Locks all properties as read-only:

type Config = {
  port: number;
};

const settings: Readonly<config> = {
  port: 3000
};

settings.port = 4000; // ❌ Error

Pick<t k>

Creates a type by selecting a subset of keys:

type UserPreview = Pick<user>;

Omit<t k>

Creates a type excluding specific keys:

type UserForm = Omit<user>;

Record<k t>

Constructs an object type with specific keys:

type Roles = "admin" | "user";

const permissions: Record<roles boolean> = {
  admin: true,
  user: false,
};

ReturnType<t>

Extracts the return type of a function:

function getUser() {
  return { id: 1, name: "Ziv" };
}

type User = ReturnType<typeof getuser>;

Parameters<t>

Gets the parameter types of a function:

function greet(name: string, age: number): void {}

type GreetArgs = Parameters<typeof greet>; // [string, number]

NonNullable<t>

Removes null and undefined:

type Name = string | null | undefined;

type SafeName = NonNullable<name>; // string

Awaited<t>

Unwraps the resolved type of a Promise:

type Data = Promise&lt;{ id: number }&gt;;

type Resolved = Awaited<data>; // { id: number }

Custom Utility Types

These utilities can be created manually using mapped types and conditional logic.


DeepPartial<t>

Recursively makes all fields optional:

type DeepPartial<t> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<t> : T[P];
};

Usage:

type Post = {
  id: number;
  meta: {
    title: string;
    tags: string[];
  };
};

type PostDraft = DeepPartial<post>;

Mutable<t>

Removes readonly from all properties:

type Mutable<t> = {
  -readonly [P in keyof T]: T[P];
};
type Locked = {
  readonly id: number;
};

type Editable = Mutable<locked>; // { id: number }

DeepReadonly<t>

Makes all properties deeply readonly:

type DeepReadonly<t> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<t> : T[P];
};

type AppState = {
  user: {
    id: number;
    name: string;
  };
};

type LockedState = DeepReadonly<appstate>;

Summary Table

Utility Type Description
Partial<t> Makes properties optional
Required<t> Makes properties required
Readonly<t> Makes properties read-only
Pick<t k> Selects specific properties
Omit<t k> Removes specific properties
Record<k t> Constructs object type with fixed keys
ReturnType<t> Extracts return type of a function
Parameters<t> Extracts parameters of a function
NonNullable<t> Removes null and undefined
Awaited<t> Unwraps the type a Promise resolves to
DeepPartial<t> Custom – Makes nested fields optional
Mutable<t> Custom – Removes readonly modifiers
DeepReadonly<t> Custom – Makes all nested fields readonly

Up next: Lesson 14 – Mapped Types and keyof — transform object types dynamically.