AniUI Academy

Utility Types, Part 1: Partial, Required, Readonly, Pick, Omit

Five built-in generic types that transform an existing type instead of redeclaring it by hand — the most commonly reached-for tool in real TypeScript code.

10 min read

A huge amount of real TypeScript work is deriving one type from another, slightly differently shaped, type — "this, but every field optional," "this, but only three of its fields." TypeScript ships a set of generic types built exactly for this, so you don't hand-write the derived shape every time.

The problem: types that repeat each other

interface User {
  id: string;
  name: string;
  email: string;
  age: number;
}
 
// Updating a user — every field is optional, since you might
// only change one at a time. Without a utility type, you'd write:
interface UserUpdate {
  id?: string;
  name?: string;
  email?: string;
  age?: number;
}

UserUpdate is entirely derivable from User — every property, just made optional. Writing it out by hand means the two types drift the moment someone adds a field to User and forgets UserUpdate. Utility types solve this by deriving the second type mechanically from the first.

Partial<T>

Makes every property of T optional:

function updateUser(id: string, changes: Partial<User>) {
  // changes might contain any subset of User's fields
}
 
updateUser("1", { name: "New Name" }); // fine — everything else omitted
updateUser("1", {});                    // also fine — an empty update

Add a field to User later, and Partial<User> picks it up automatically, still optional, with zero extra code.

Required<T>

The opposite of Partial — strips ? from every property, making all of them mandatory:

interface Settings {
  theme?: string;
  fontSize?: number;
}
 
function applySettings(settings: Required<Settings>) {
  // theme and fontSize are both guaranteed present here
}
 
applySettings({ theme: "dark", fontSize: 14 }); // fine
applySettings({ theme: "dark" });
// Property 'fontSize' is missing.

Useful for a function that needs every optional field filled in — after merging user settings with defaults, for instance.

Readonly<T>

Adds readonly to every property of T, without writing it on each one by hand:

const config: Readonly<Settings> = { theme: "dark", fontSize: 14 };
config.theme = "light";
// Cannot assign to 'theme' because it is a read-only property.

Same compile-time-only behaviour as readonly on a single property from earlier in this track — this utility type just saves repeating it across every field.

Pick<T, Keys>

Builds a new type containing only the listed properties of T:

type UserPreview = Pick<User, "id" | "name">;
// { id: string; name: string }
 
const preview: UserPreview = { id: "1", name: "Amara" };

The second argument is a union of string literal keys — each one must actually exist on T, or it's a compile error, which is exactly the safety net that makes this better than redeclaring { id: string; name: string } by hand: a typo in the key name is caught immediately.

Omit<T, Keys>

The inverse of Pick — keeps everything except the listed properties:

type PublicUser = Omit<User, "email">;
// { id: string; name: string; age: number }
 
const publicUser: PublicUser = { id: "1", name: "Amara", age: 29 };

Omit is usually more convenient than Pick when you want "almost everything" — listing the one or two fields to exclude is shorter than listing every field you want to keep.

How Partial and friends are actually defined

Worth a preview, even though the mechanism (a mapped type) is covered in full later in this track — Partial<T> is not a special compiler built-in, just an ordinary generic type defined in TypeScript's standard library:

type Partial<T> = {
  [K in keyof T]?: T[K];
};

Nothing here is off-limits to you — once mapped types are covered, you'll be able to write your own version of any of these five from scratch.

Try it yourself

Try it yourself
Loading playground...

What to remember

  • Partial<T> makes every property optional; Required<T> makes every property mandatory.
  • Readonly<T> marks every property readonly, at compile time only — the same guarantee as a single readonly property, applied to all of them.
  • Pick<T, Keys> keeps only listed properties; Omit<T, Keys> keeps everything except the listed ones.
  • All five derive a new type from an existing one mechanically, so the derived type stays correct as the source type changes.

Check yourself

4 questions · pass 3/4 to unlock Utility Types, Part 2: Record, Exclude, Extract, and the Function Ones

up to 50
  1. 1.Given interface User { name: string; age: number }, what does Partial<User> produce?

  2. 2.What is Pick<User, "name"> for the User interface above?

  3. 3.What is Omit<User, "age">?

  4. 4.What does Readonly<T> change that plain readonly on individual properties doesn't?

4 left to answer