TypeScript Utility Types

Utility types are built-in generic types that transform existing types into new ones. Instead of rewriting a type from scratch every time a variation is needed, utility types apply a transformation — making all properties optional, readonly, required, or picking only a subset of properties. They ship with TypeScript and require no installation.

Why Utility Types?

  Original Type:
  +-----------+-----------+
  | User                  |
  |-----------+-----------|
  | id        | number    |  required
  | name      | string    |  required
  | email     | string    |  required
  | password  | string    |  required
  +-----------+-----------+

  Partial<User> — all optional (for update operations):
  +-----------+-----------+
  | id?       | number    |  optional
  | name?     | string    |  optional
  | email?    | string    |  optional
  | password? | string    |  optional
  +-----------+-----------+

  Pick<User, "id" | "name"> — only selected fields:
  +-----------+-----------+
  | id        | number    |  required
  | name      | string    |  required
  +-----------+-----------+

Base Type for Examples

interface User {
    id: number;
    name: string;
    email: string;
    password: string;
    age: number;
    isAdmin: boolean;
}

Partial<T>

Makes all properties of a type optional. Useful for update payloads where only a few fields change at a time.

type PartialUser = Partial<User>;
// All properties become optional (?)

function updateUser(id: number, changes: Partial<User>): void {
    console.log("Updating user " + id + " with: ", changes);
}

updateUser(1, { name: "Rekha Sharma" });         // Only name — valid
updateUser(2, { email: "new@mail.com", age: 30 }); // Only email and age — valid
updateUser(3, {}); // Empty object — valid (all fields optional)

Required<T>

Makes all properties required — the opposite of Partial. Useful when an optional type must be fully filled before saving.

interface DraftCourse {
    title?: string;
    description?: string;
    price?: number;
    level?: string;
}

// Force all fields to be provided before publishing
type PublishedCourse = Required<DraftCourse>;

let course: PublishedCourse = {
    title: "TypeScript Mastery",
    description: "Complete TypeScript guide",
    price: 999,
    level: "Beginner"
    // All fields required — missing any causes error
};

Readonly<T>

Makes all properties readonly. Once the object is created, no property can be changed. Ideal for configuration objects and constants.

type ReadonlyUser = Readonly<User>;

let adminUser: Readonly<User> = {
    id: 1,
    name: "Suresh Admin",
    email: "suresh@estudy247.com",
    password: "hashed_pass",
    age: 35,
    isAdmin: true
};

adminUser.name = "Changed"; // Error: Cannot assign to 'name' (read-only)
adminUser.age  = 36;        // Error: Cannot assign to 'age' (read-only)

Pick<T, K>

Creates a new type with only the selected properties from the original type. Useful for creating trimmed-down versions for display or API responses.

// Public profile — only name and email exposed
type PublicProfile = Pick<User, "id" | "name" | "email">;

let profile: PublicProfile = {
    id: 5,
    name: "Tara Mehta",
    email: "tara@mail.com"
    // password, age, isAdmin — NOT included
};

console.log(profile.name);     // Tara Mehta
console.log(profile.password); // Error: 'password' does not exist on type 'PublicProfile'

Omit<T, K>

Creates a new type by removing specific properties from the original. The inverse of Pick.

// Remove password before sending user data to the client
type SafeUser = Omit<User, "password">;

function getPublicUser(user: User): SafeUser {
    let { password, ...safeData } = user;
    return safeData;
}

let fullUser: User = { id: 3, name: "Vimal", email: "v@mail.com", password: "secret", age: 28, isAdmin: false };
let publicUser = getPublicUser(fullUser);

console.log(publicUser.name);     // Vimal
console.log(publicUser.password); // Error: 'password' does not exist on type 'SafeUser'

Record<K, V>

Creates an object type where all keys are of type K and all values are of type V. Perfect for dictionaries, lookup tables, and maps.

// Map course IDs to course names
type CourseCatalog = Record<number, string>;

let catalog: CourseCatalog = {
    1001: "TypeScript Basics",
    1002: "React Fundamentals",
    1003: "Node.js Backend"
};

console.log(catalog[1001]); // TypeScript Basics
console.log(catalog[1003]); // Node.js Backend

// Map role names to permission arrays
type RolePermissions = Record<"admin" | "instructor" | "student", string[]>;

let permissions: RolePermissions = {
    admin:      ["read", "write", "delete", "manage"],
    instructor: ["read", "write", "create-course"],
    student:    ["read", "enroll"]
};

Exclude<T, U>

Removes specific members from a union type.

type AllRoles = "admin" | "instructor" | "student" | "guest";

// Remove "guest" from the union
type AuthenticatedRoles = Exclude<AllRoles, "guest">;
// Result: "admin" | "instructor" | "student"

let role: AuthenticatedRoles = "student"; // Valid
let role2: AuthenticatedRoles = "guest";  // Error

Extract<T, U>

Keeps only the members that exist in both types — the opposite of Exclude.

type A = "a" | "b" | "c" | "d";
type B = "b" | "d" | "f";

type Common = Extract<A, B>;
// Result: "b" | "d"  (only common members)

NonNullable<T>

Removes null and undefined from a type.

type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>;
// Result: string

function processName(name: NonNullable<string | null>): string {
    return name.toUpperCase(); // Safe — null excluded
}

ReturnType<T>

Extracts the return type of a function type.

function getStudent() {
    return { id: 1, name: "Arjun", grade: "A" };
}

type StudentData = ReturnType<typeof getStudent>;
// { id: number; name: string; grade: string; }

let data: StudentData = getStudent();
console.log(data.name); // Arjun

Parameters<T>

Extracts the parameter types of a function as a tuple.

function createOrder(productId: number, quantity: number, address: string): void {
    console.log("Order placed");
}

type OrderParams = Parameters<typeof createOrder>;
// [productId: number, quantity: number, address: string]

let args: OrderParams = [1001, 2, "12 MG Road, Bengaluru"];
createOrder(...args); // Order placed

Utility Types Quick Reference

Utility TypeWhat It DoesCommon Use Case
Partial<T>All properties optionalPATCH / update operations
Required<T>All properties requiredFinal submission validation
Readonly<T>All properties readonlyImmutable config, constants
Pick<T, K>Keep only listed propertiesPublic profile, API response
Omit<T, K>Remove listed propertiesStrip passwords, sensitive data
Record<K, V>Object with typed keys and valuesLookup tables, dictionaries
Exclude<T, U>Remove union membersFilter out roles or statuses
Extract<T, U>Keep common union membersShared role permissions
NonNullable<T>Remove null and undefinedSafe value assertions
ReturnType<T>Get function's return typeType output of factory functions
Parameters<T>Get function's parameter typesForward function arguments

Practical Example — Course Platform

interface CourseDetails {
    courseId: number;
    title: string;
    instructor: string;
    description: string;
    price: number;
    isPublished: boolean;
    secretNotes: string;
}

// For the admin dashboard — full details
type AdminView = CourseDetails;

// For the public listing — no secret notes, no internal ID
type PublicCourse = Omit<CourseDetails, "secretNotes">;

// For the update API — allow partial updates
type CourseUpdate = Partial<Omit<CourseDetails, "courseId">>;

// For a read-only snapshot
type CourseSnapshot = Readonly<PublicCourse>;

// Lookup table for multiple courses
type CourseLookup = Record<number, PublicCourse>;

function updateCourse(id: number, changes: CourseUpdate): void {
    console.log("Updating course " + id);
    console.log(changes);
}

// Only update title and price — valid
updateCourse(1001, { title: "TypeScript Complete", price: 1299 });

// Create a lookup
let courseLookup: CourseLookup = {
    1001: {
        courseId: 1001,
        title: "TypeScript Mastery",
        instructor: "Anand Rao",
        description: "Full TypeScript course",
        price: 999,
        isPublished: true
    }
};

console.log(courseLookup[1001].title); // TypeScript Mastery

Leave a Comment