TypeScript Lesson 10: Utility Types
TypeScript has built-in utility types that transform existing types. These save huge amounts of typing and are used constantly in real codebases.
Essential Utility Types
interface User {
id: number;
name: string;
email: string;
password: string;
role: "user" | "admin";
createdAt: Date;
}
// Partial: all properties optional
type UserUpdate = Partial<User>;
// { id?: number; name?: string; email?: string; ... }
// Required: all properties required (reverse of Partial)
type StrictConfig = Required<Config>;
// Readonly: nothing can be reassigned
type FrozenUser = Readonly<User>;
const u: FrozenUser = getUser();
u.name = "Bob"; // ❌ Error
// Pick: keep only specified properties
type UserPublic = Pick<User, "id" | "name" | "email">;
// Safe to send to frontend — no password!
// Omit: exclude specified properties
type UserWithoutPassword = Omit<User, "password">;
// Record: map keys to values
type Roles = Record<"user" | "admin" | "guest", string[]>;
// { user: string[]; admin: string[]; guest: string[] }
More Utility Types
type Status = "pending" | "active" | "done";
// Exclude: remove from union
type ActiveStatus = Exclude<Status, "done">; // "pending" | "active"
// Extract: keep only matching
type DoneStatus = Extract<Status, "done" | "pending">; // "pending" | "done"
// ReturnType: get what a function returns
function createUser() { return { id: 1, name: "Alice" }; }
type UserObj = ReturnType<typeof createUser>; // { id: number; name: string }
// Parameters: get function params as tuple
type FnParams = Parameters<typeof createUser>;
🏋️ Practice Task
Given a full User interface, use utility types to create: UserPublicProfile (no password/role), CreateUserDTO (no id/createdAt), UpdateUserDTO (all optional, no id/createdAt), UserSummary (only id and name). No rewriting properties — use only Omit, Pick, Partial.
💡 Hint: type UserPublicProfile = Omit