Lesson 7 of 13 · 0 of 1 exercises solved
Utility Types
TypeScript includes built-in utility types such as Partial, Pick and Omit that build new types from existing ones. Using them saves you from writing and maintaining near-duplicate type definitions.
interface User {
id: number
name: string
email: string
password: string
createdAt: Date
role: "user" | "admin"
}
// Partial<T> — all properties become optional
type UserUpdate = Partial<User>
// { id?: number; name?: string; email?: string; ... }
// Required<T> — all optional properties become required
type StrictUser = Required<UserUpdate>
// Readonly<T> — all properties become readonly
type FrozenUser = Readonly<User>
// Pick<T, Keys> — select a subset of properties
type UserPublic = Pick<User, "id" | "name" | "role">
// { id: number; name: string; role: "user" | "admin" }
// Omit<T, Keys> — exclude properties
type UserWithoutPassword = Omit<User, "password">
// Record<Keys, Type> — create an object type with specific keys
type RolePermissions = Record<"user" | "admin", string[]>
const perms: RolePermissions = {
user: ["read"],
admin: ["read", "write", "delete"],
}
// Exclude<T, U> — remove members from union
type NotAdmin = Exclude<"user" | "admin" | "guest", "admin">
// "user" | "guest"
// Extract<T, U> — keep only members assignable to U
type StringOrNumber = Extract<string | number | boolean, string | number>
// string | number// ReturnType<T> — extract return type of a function
function getUser() {
return { id: 1, name: "Alice", email: "alice@example.com" }
}
type UserFromFn = ReturnType<typeof getUser>
// { id: number; name: string; email: string }
// Parameters<T> — extract parameter types as tuple
function createPost(title: string, body: string, authorId: number) {}
type CreatePostArgs = Parameters<typeof createPost>
// [string, string, number]
// Awaited<T> — unwrap Promise type
type ResolvedUser = Awaited<Promise<User>> // User
// NonNullable<T> — remove null and undefined
type DefinitelyString = NonNullable<string | null | undefined>
// string
// Practical example — form handling pattern
type FormValues = Omit<User, "id" | "createdAt">
type FormErrors = Partial<Record<keyof FormValues, string>>
function validateUser(values: FormValues): FormErrors {
const errors: FormErrors = {}
if (!values.name) errors.name = "Name is required"
if (!values.email.includes("@")) errors.email = "Invalid email"
if (values.password.length < 8) errors.password = "Min 8 characters"
return errors
}Practice
Given interface User { id: number; name: ; email: string; role: "admin" | "reader" }, declare UserPreview = Pick<User, "id" | "name">, UserPatch = Partial<Omit<User, "id">>, and write updateUser(user: User, patch: UserPatch): User that returns a new object with the patch applied.
Exercise
3 checksPick, Omit and Partial
interface User {
id: number
name: string
email: string
role: "admin" | "reader"
}
// type UserPreview = ...
// type UserPatch = ...
function updateUser(user, patch) {
return user
}
const ada = { id: 1, name: "Ada", email: "ada@example.com", role: "reader" }
console.log(updateUser(ada, { role: "admin" }))
Press Run to try your code, then Check answer to grade it.Finished reading?1 exercise still open. You can come back to it later.
Tip: use the ← and → keys to move between lessons.