Interview Q&A / TypeScript

BeginnerIn-depth3 min readUpdated 2 Oct 2026

What are utility types in TypeScript, such as Partial, Required, Pick, Omit and Record?

SHORT ANSWER

Utility types are built-in generic types that create a new type from an existing one. Partial makes all properties optional, Required makes them all required, Pick keeps only chosen keys, Omit removes chosen keys, and Record builds an object type from a set of keys and a value type.

Explain it simply

Think of a master student record in your college office with every field: name, roll number, phone, address, marks. Different forms need different slices of it:

  • The "update your details" form lets you change any field, but you do not have to fill all of them. That is Partial.
  • The hall ticket only shows name and roll number. That is Pick.
  • The public result list shows everything except phone and address. That is Omit.

Utility types let you derive these shapes from the one master type, instead of rewriting them by hand. When the master type changes, every derived type updates automatically.

Example

ts
interface Student {
  id: number;
  name: string;
  email: string;
  phone?: string;
}

// Partial<T>: every property optional
type StudentUpdate = Partial<Student>;
function updateStudent(id: number, changes: StudentUpdate): void {}
updateStudent(1, { email: "new@example.com" }); // OK: only one field

// Required<T>: every property required (removes ?)
type CompleteStudent = Required<Student>; // phone is now required

// Pick<T, Keys>: keep only these properties
type HallTicket = Pick<Student, "id" | "name">;
// { id: number; name: string }

// Omit<T, Keys>: remove these properties
type NewStudent = Omit<Student, "id">; // id is created by the database

// Record<Keys, Value>: object with these keys and this value type
type Grade = "A" | "B" | "C";
const gradeCount: Record<Grade, number> = { A: 12, B: 20, C: 5 };
// Missing a key or adding "D" is an error

// Readonly<T>: no reassignment of properties
const config: Readonly<Student> = { id: 1, name: "Asha", email: "a@x.com" };
// config.name = "Ravi"; // Error: name is read-only

How it works

Most utility types are mapped types: they loop over the keys of a type and transform each property. You could write Partial yourself:

ts
type MyPartial<T> = { [K in keyof T]?: T[K] };
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };
type MyRecord<K extends keyof any, V> = { [P in K]: V };

Omit is built from Pick and Exclude: it picks every key except the ones you exclude.

Other useful ones:

  • Readonly<T>: all properties read-only.
  • ReturnType<typeof fn> and Parameters<typeof fn>: types taken from a function.
  • Awaited<T>: the value type inside a Promise.
  • NonNullable<T>: removes null and undefined.
  • Exclude<T, U> and Extract<T, U>: filter members of a union.

Real-world use

  • Partial<T> for PATCH requests and form state where fields are filled one by one.
  • Omit<T, "id" | "createdAt"> for "create" payloads where the server generates those fields.
  • Pick<T, ...> to type a small card component that needs only a few fields of a big object.
  • Record<string, number> for lookup maps, and Record<Status, string> to make sure every status has a label.
  • ReturnType to type the result of a function you do not control.

Common mistakes

  • Expecting Partial and Readonly to be deep. They only affect top-level properties; nested objects are unchanged.
  • Thinking Readonly freezes the object at runtime. It is a compile-time check only; use Object.freeze for runtime.
  • Typo in Omit keys. Omit accepts any string, so Omit<Student, "emial"> compiles silently and removes nothing. Pick does check that keys exist.
  • Using Record<string, T> and assuming every key lookup returns a T. Without the noUncheckedIndexedAccess option, obj["missing"] is typed as T even though it is undefined at runtime.

What to say in the interview

"Utility types are built-in generics that transform an existing type, so I keep one source of truth and derive the rest. Partial makes all properties optional, which I use for update payloads; Required does the opposite; Pick keeps selected keys and Omit removes them, for example omitting id for a create request; and Record builds an object type from a key type and a value type, useful for lookup tables. They are implemented as mapped types over keyof T. I keep in mind that they are shallow and only exist at compile time."

Follow-up questions

  • How would you write Partial yourself?
  • How would you make a DeepPartial type?
  • What is the difference between Omit and Exclude?
  • How do ReturnType and Parameters work?

Go deeper

Read these once the basics above feel easy.

A recursive DeepPartial can be written as type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K] };, though real versions need special cases for arrays, functions and dates. Omit is not checked because its definition is Omit<T, K extends keyof any>; if you want typo protection, define your own type StrictOmit<T, K extends keyof T> = Omit<T, K>;. ReturnType is built with a conditional type and infer: T extends (...args: any) => infer R ? R : any.

#utility-types#generics#mapped-types

Related questions

Practise more TypeScript questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open TypeScript quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.