Built-in Utility Types

0/5 in this phase0/21 across the roadmap

📖 Concept

TypeScript ships with built-in utility types that transform existing types — making properties optional, required, readonly, or extracting/excluding parts.

Object transformers:

  • Partial<T> — All properties optional
  • Required<T> — All properties required
  • Readonly<T> — All properties readonly
  • Pick<T, K> — Select specific properties
  • Omit<T, K> — Remove specific properties
  • Record<K, V> — Object with keys K and values V

Union transformers:

  • Exclude<T, U> — Remove types from union
  • Extract<T, U> — Keep only matching types
  • NonNullable<T> — Remove null and undefined

Function transformers:

  • ReturnType<T> — Extract return type
  • Parameters<T> — Extract parameter types as tuple
  • ConstructorParameters<T> — Parameters of a constructor

String transformers:

  • Uppercase<T>, Lowercase<T>, Capitalize<T>, Uncapitalize<T>

Understanding how these work internally (using mapped types, conditional types, and infer) is key to building your own utility types in Phase 3.

🏠 Real-world analogy: Utility types are like photo filters. You take an existing photo (type) and apply transformations — make it grayscale (Readonly), crop it (Pick), blur parts (Omit). The original photo remains unchanged; you get a new version.

💻 Code Example

codeTap to expand ⛶
1interface User {
2 id: number;
3 name: string;
4 email: string;
5 age: number;
6 role: "admin" | "user";
7}
8
9// Partial — all properties become optional
10type UpdateUser = Partial<User>;
11// { id?: number; name?: string; email?: string; ... }
12function updateUser(id: number, updates: Partial<User>): void {
13 // Can pass any subset of User properties
14}
15updateUser(1, { name: "Bob" }); // ✅
16updateUser(1, { name: "Bob", age: 31 }); // ✅
17
18// Required — opposite of Partial
19interface Config {
20 apiUrl?: string;
21 timeout?: number;
22}
23type StrictConfig = Required<Config>;
24// { apiUrl: string; timeout: number; } — no more optional!
25
26// Readonly — prevent mutation
27type ImmutableUser = Readonly<User>;
28// const u: ImmutableUser = { ... };
29// u.name = "Bob"; // ❌ Error: readonly
30
31// Pick — select properties
32type UserPreview = Pick<User, "id" | "name">;
33// { id: number; name: string; }
34
35// Omit — remove properties
36type UserWithoutEmail = Omit<User, "email">;
37// { id: number; name: string; age: number; role: ... }
38
39// Record — typed key-value map
40type UserRoles = Record<string, "admin" | "user" | "guest">;
41const roles: UserRoles = {
42 alice: "admin",
43 bob: "user"
44};
45
46type StatusMessages = Record<"loading" | "success" | "error", string>;
47const messages: StatusMessages = {
48 loading: "Please wait...",
49 success: "Done!",
50 error: "Something went wrong"
51};
52
53// Exclude and Extract (on unions)
54type AllTypes = string | number | boolean | null | undefined;
55type NotNull = Exclude<AllTypes, null | undefined>;
56// string | number | boolean
57type OnlyStringOrNumber = Extract<AllTypes, string | number>;
58// string | number
59
60// NonNullable
61type MaybeString = string | null | undefined;
62type DefiniteString = NonNullable<MaybeString>; // string
63
64// ReturnType — extract function return type
65function fetchUsers() {
66 return [{ id: 1, name: "Alice" }];
67}
68type Users = ReturnType<typeof fetchUsers>;
69// { id: number; name: string; }[]
70
71// Parameters — extract function params as tuple
72function createUser(name: string, age: number, role?: string) { }
73type CreateUserParams = Parameters<typeof createUser>;
74// [name: string, age: number, role?: string]
75
76// Combining utility types
77type CreateUserDTO = Omit<User, "id">; // Everything except id
78type UserPatch = Partial<Omit<User, "id" | "role">>; // Optional fields, no id/role
79
80// Awaited — extract the resolved type of a Promise
81type PromiseResult = Awaited<Promise<Promise<string>>>;
82// string (deeply unwraps)

🏋️ Practice Exercise

Mini Exercise:

  1. Create an UpdateDTO type that makes all fields of User optional EXCEPT id (required)
  2. Use Record to create a typed dictionary mapping HTTP status codes to messages
  3. Extract the return type of an async function using Awaited<ReturnType<typeof fn>>
  4. Create a PublicUser type that omits sensitive fields like password and email
  5. Combine Pick, Partial, and Required to create a complex DTO type

⚠️ Common Mistakes

  • Confusing Omit and ExcludeOmit works on object types (removes properties); Exclude works on union types (removes union members)

  • Using Partial when only some fields should be optional — use Pick + Partial combination or intersection for precise control

  • Forgetting that Readonly is shallow — nested objects inside a Readonly<T> can still be mutated

  • Not knowing that Record<string, T> allows ANY string key — for specific keys, use Record<'a' | 'b', T>

  • Using ReturnType with a function value instead of a type — use ReturnType<typeof myFunction>, not ReturnType<myFunction>

💼 Interview Questions

🎤 Mock Interview

Practice a live interview for Built-in Utility Types