Built-In Utility Types
Introduction
TypeScript ships utility types that transform existing types—making fields optional, picking keys, or building records without duplicating definitions. They power library typings and keep your models DRY. This chapter covers the most used utilities and a light peek at conditional types that implement many of them.
Prerequisites
Partial and Required
Make all properties optional or required:
interface User {
id: number;
name: string;
email: string;
}
type UserUpdate = Partial<User>;
const patch: UserUpdate = { name: "Ada" };
type CompleteUser = Required<UserUpdate>;Code explanation:
Partial<User>is{ id?: number; name?: string; email?: string }Required<T>removes optionality from every property ofT
Common for PATCH endpoints and form drafts.
Readonly
Immutable properties at type level:
type FrozenUser = Readonly<User>;
const u: FrozenUser = { id: 1, name: "Ada", email: "a@example.com" };
// u.name = "Lin"; // ErrorReadonlyArray<T> (or readonly T[]) prevents mutating methods like push.
Record: Dictionary Types
type Role = "admin" | "member" | "guest";
type RoleLabels = Record<Role, string>;
const labels: RoleLabels = {
admin: "Administrator",
member: "Member",
guest: "Guest",
};Record<Keys, Value> maps each key in Keys to Value.
type StringDictionary = Record<string, number>;
const scores: StringDictionary = {
math: 90,
english: 85,
};Pick and Omit
Select or remove properties:
type UserPreview = Pick<User, "id" | "name">;
type UserWithoutEmail = Omit<User, "email">;Code explanation:
Pickkeeps listed keysOmitremoves listed keys—handy for public DTOs without internal fields
Exclude and Extract (Unions)
Filter union members:
type Status = "pending" | "done" | "failed" | "cancelled";
type Finished = Exclude<Status, "pending">;
// "done" | "failed" | "cancelled"
type SuccessOnly = Extract<Status, "done" | "pending">;
// "done" | "pending"Code explanation:
Exclude<T, U>removes fromTanything assignable toUExtract<T, U>keeps members ofTassignable toU
Often used with union literals and event names.
NonNullable
Remove null and undefined from a type:
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>;
// stringReturnType and Parameters
Extract function types:
function createUser(name: string, age: number) {
return { id: 1, name, age };
}
type NewUser = ReturnType<typeof createUser>;
type CreateUserParams = Parameters<typeof createUser>;Code explanation:
typeof createUserrefers to the function value’s type- Useful when refactoring—return type stays in sync with implementation
Combining Utilities
interface Todo {
id: string;
title: string;
done: boolean;
dueAt?: string;
}
type TodoPatch = Partial<Pick<Todo, "title" | "done" | "dueAt">>;
type ReadonlyTodo = Readonly<Todo>;Conditional Types (Conceptual)
Many utilities are built with conditional types:
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">;
type B = IsString<number>;A is true, B is false. The pattern T extends U ? X : Y selects types based on structure.
infer extracts types inside conditionals (used in library typings):
type ElementType<T> = T extends (infer U)[] ? U : never;
type Item = ElementType<string[]>;
// stringYou rarely write these daily; you use ReturnType, Awaited, etc. that depend on them.
Tip
Read Utility Source for Learning
In VS Code, Go to Definition on Partial or Pick shows simplified built-in declarations—excellent for advanced study.
Practical Example: API Layers
Code explanation:
- Public API omits internal fields
- Create omits server-generated
id - Update allows partial fields
Quick Reference Table
| Utility | Purpose |
|---|---|
Partial<T> | All properties optional |
Required<T> | All properties required |
Readonly<T> | All properties readonly |
Record<K, V> | Object with keys K, values V |
Pick<T, K> | Subset of properties |
Omit<T, K> | Remove properties |
Exclude<T, U> | Remove from union |
Extract<T, U> | Keep from union |
NonNullable<T> | Drop null/undefined |
ReturnType<F> | Function return type |
Parameters<F> | Function parameter tuple |
FAQ
Utility types at runtime?
No. They exist only for type checking.
Pick vs manual interface?
Pick stays in sync when User grows—only selected keys appear in the result type.
Can I nest utilities?
Yes: Partial<Pick<User, "name" | "email">> is common.
Omit vs Exclude?
Omit works on object keys. Exclude works on union members.
What is Awaited?
Unwraps Promise types—useful for async function results (TypeScript 4.5+).
Should I reimplement Partial?
No. Use built-ins—they are standard and optimized for the compiler.