Intermediate0 questionsFull Guide

TypeScript Utility Types — Complete Interview Guide

Master TypeScript's built-in utility types — Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, ReturnType, and more. Learn what each does, when to use it, and how to implement them yourself using mapped and conditional types.

The Mental Model

TypeScript's utility types are a standard library for type transformations — the same idea as lodash for runtime values, but for types at compile time. Just as lodash.pick(obj, keys) extracts a subset of an object's properties at runtime, Pick<User, 'id' | 'name'> extracts a subset of User's type definition at compile time. Each utility type is a generic that takes one or more types and produces a transformed type — and every one of them is implemented using the same mapped and conditional type primitives you can write yourself.

The Explanation

The Partial Family — Modifying Optionality

// Partial<T> — makes every property optional
interface User { id: number; name: string; email: string; }
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; }

// Essential for update/patch functions:
function updateUser(id: number, changes: Partial<User>): User { /* ... */ }
updateUser(1, { name: "Bob" }); // Only name — perfectly valid

// Required<T> — makes every property required (removes ?)
interface Config { host?: string; port?: number; debug?: boolean; }
type StrictConfig = Required<Config>;
// { host: string; port: number; debug: boolean; }

// Readonly<T> — makes every property readonly
const config: Readonly<Config> = { host: "localhost", port: 3000 };
config.host = "example.com"; // Error: Cannot assign to 'host' — readonly

Pick and Omit — Selecting Properties

interface Product {
  id: number;
  title: string;
  description: string;
  price: number;
  internalCode: string; // sensitive — don't expose to client
}

// Pick — include only listed keys
type ProductSummary = Pick<Product, "id" | "title" | "price">;
// { id: number; title: string; price: number; }

// Omit — exclude listed keys (dual of Pick)
type PublicProduct = Omit<Product, "internalCode">;
// { id: number; title: string; description: string; price: number; }

// Prefer Omit when you want to exclude a few sensitive fields from a large type
// Prefer Pick when you want to select a small subset from a large type

Record — Typed Dictionaries

// Record<K, V> — a type with keys K and values V
type UserMap = Record<string, User>;
// { [key: string]: User }

// More precise — limit the keys to a union
type Permission = "read" | "write" | "delete";
type RolePermissions = Record<Permission, boolean>;
// { read: boolean; write: boolean; delete: boolean; }
// TypeScript will error if you miss a key — exhaustive check

const adminPerms: RolePermissions = { read: true, write: true, delete: true };
const guestPerms: RolePermissions = { read: true, write: false }; // Error: missing 'delete'

Exclude and Extract — Filtering Union Members

type AllStatus = "active" | "inactive" | "deleted" | "banned";

// Exclude removes matching members from a union
type VisibleStatus = Exclude<AllStatus, "deleted" | "banned">;
// "active" | "inactive"

// Extract keeps only matching members
type ProblematicStatus = Extract<AllStatus, "deleted" | "banned">;
// "deleted" | "banned"

// NonNullable removes null and undefined
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>;
// string

// Practical use: filtering a union to only object types
type OnlyFunctions = Extract<string | number | (() => void), Function>;
// () => void

ReturnType, Parameters, and InstanceType

function createUser(name: string, age: number): User { /* ... */ }

// ReturnType — extracts the return type of a function
type CreatedUser = ReturnType<typeof createUser>;
// User

// Parameters — extracts a tuple of the parameter types
type CreateUserArgs = Parameters<typeof createUser>;
// [name: string, age: number]

// InstanceType — extracts the instance type of a constructor
class UserService { getUser(id: number): User { /* ... */ } }
type UserServiceInstance = InstanceType<typeof UserService>;
// UserService

// These are invaluable when you don't control the source types —
// you can derive types from functions/classes you import from libraries

Implementing Utility Types Yourself

Every built-in utility type is implemented using mapped or conditional types. Understanding the implementations is a strong interview signal:

// How Partial is implemented in TypeScript's lib.d.ts
type MyPartial<T> = {
  [P in keyof T]?: T[P];
};

// How Required is implemented
type MyRequired<T> = {
  [P in keyof T]-?: T[P]; // -? removes the optional modifier
};

// How Readonly is implemented
type MyReadonly<T> = {
  readonly [P in keyof T]: T[P];
};

// How Pick is implemented
type MyPick<T, K extends keyof T> = {
  [P in K]: T[P];
};

// How Record is implemented
type MyRecord<K extends keyof any, T> = {
  [P in K]: T;
};

// How Exclude is implemented (conditional type distributing over union)
type MyExclude<T, U> = T extends U ? never : T;

Common Misconceptions

⚠️

Many developers think Partial<T> makes all nested properties optional recursively — it only makes the top-level properties optional. Nested objects remain fully required. You need a custom DeepPartial type for recursive optionality.

⚠️

Many developers confuse Omit and Exclude — Omit works on object types and removes properties by key name. Exclude works on union types and removes members by type. They are solving different problems.

⚠️

Many developers think Record<string, T> and { [key: string]: T } are different types — they produce identical index signatures. Record is preferred for readability and for using union keys, which the index signature syntax cannot express.

⚠️

Many developers think ReturnType<T> requires the actual function — it requires typeof theFunction. ReturnType<typeof createUser> not ReturnType<createUser>.

⚠️

Many developers think utility types are magic compiler features — every one is implemented using mapped types and conditional types that you can write yourself. The TypeScript source for all built-in utilities is in lib.es5.d.ts and is well worth reading.

⚠️

Many developers reach for Partial on function parameters instead of using optional properties — Partial<Options> as a parameter type is correct. But for function return types, Partial can hide missing data that callers expect to be present.

Where You'll See This in Real Code

PATCH API endpoints: function patchUser(id: string, data: Partial<User>) is the idiomatic pattern for update operations where only changed fields are sent — Partial makes all fields optional without creating a separate PartialUser interface.

Config objects with defaults: Required<AppConfig> as the internal type after merging with defaults ensures every optional config option has been resolved before it reaches internal code — a clean way to enforce completeness after a merge step.

Permission maps: Record<Permission, boolean> for role-based access control ensures every permission key is explicitly set when creating a role object, giving exhaustive compile-time checking that a plain object literal would not provide.

Deriving types from imported libraries: ReturnType<typeof libraryFunction> and Parameters<typeof libraryFunction> are essential when a library doesn't export its types directly — you can derive what you need from the function signatures themselves.

React component prop subsets: Pick<ButtonProps, 'onClick' | 'disabled' | 'children'> creates a minimal prop interface for a wrapper component without manually duplicating individual props — stays in sync automatically when ButtonProps changes.

Form state types: Partial<FormValues> for draft state that is progressively filled in, transitioning to FormValues (fully required) only on submit — models the two states with type-level precision.

Interview Cheat Sheet

  • Partial<T> — all properties optional (top-level only, not recursive)
  • Required<T> — all properties required (removes ?)
  • Readonly<T> — all properties readonly
  • Pick<T, K> — keep only keys K from T
  • Omit<T, K> — remove keys K from T (dual of Pick)
  • Record<K, V> — object type with keys K and values V; K can be a union for exhaustive keys
  • Exclude<T, U> — remove union members assignable to U from union T
  • Extract<T, U> — keep only union members assignable to U from union T
  • NonNullable<T> — remove null and undefined from T
  • ReturnType<typeof fn> — extract the return type of a function
  • Parameters<typeof fn> — extract parameter types as a tuple
  • All utility types are implemented with mapped/conditional types — you can write your own
💡

How to Answer in an Interview

  • 1.Group utility types by what they operate on: 'Partial, Required, Readonly, Pick, Omit operate on object types. Record creates typed dictionaries. Exclude, Extract, NonNullable operate on union types. ReturnType, Parameters extract information from function types.'
  • 2.Know the implementations — being able to write MyPartial<T> = { [P in keyof T]?: T[P] } shows you understand the underlying mechanics, not just the names. It's a strong signal at senior level.
  • 3.The Omit vs Exclude distinction trips many candidates: 'Omit removes properties from an object type by key name. Exclude removes members from a union type. Different problems, different tools.'
  • 4.Give a practical use case for each one you mention — abstract definitions without concrete examples are weak. 'Partial for PATCH endpoints. Record<Permission, boolean> for exhaustive role maps. ReturnType when a library doesn't export its types.'

Practice Questions

No questions tagged to this topic yet.

Related Topics

TypeScript Types vs Interfaces — Complete Interview Guide
Intermediate·8–12 Qs
TypeScript Mapped Types — Complete Interview Guide
Advanced·6–10 Qs
TypeScript Generics — Complete Interview Guide
Intermediate·8–12 Qs
TypeScript Conditional Types — Complete Interview Guide
Advanced·6–10 Qs
🎯

Can you answer these under pressure?

Reading answers is not the same as knowing them. Practice saying them out loud with AI feedback — that's what builds real interview confidence.

Practice Free →Try Output Quiz