π§° TypeScript Utility Types: Your Magic Toolbox
Imagine you have a LEGO set. You built a castle, but now you want to change just a few pieces without breaking the whole thing. TypeScript Utility Types are like special LEGO tools that help you reshape your creations perfectly!
π― What Are Utility Types?
Think of a type as a recipe card. It tells you exactly what ingredients (properties) something needs.
Utility Types are like kitchen gadgets that transform your recipe cards:
- Want to make some ingredients optional? β
- Need to pick only a few ingredients? β
- Remove some ingredients entirely? β
TypeScript gives you these tools built-in!
1οΈβ£ Partial and Required: The Optional/Mandatory Switch
π Partial - Make Everything Optional
Imagine a form where you only fill in what you want to update.
type User = {
name: string;
age: number;
email: string;
};
// Partial makes ALL fields optional
type UpdateUser = Partial<User>;
// Now this is valid:
const update: UpdateUser = {
name: "Sam" // Only updating name!
};
What happened? Every property got a ? added automatically!
π Required - Make Everything Mandatory
The opposite! Forces all optional fields to be required.
type Settings = {
theme?: string;
volume?: number;
};
// Required removes all the ?'s
type FullSettings = Required<Settings>;
// Now you MUST provide both:
const settings: FullSettings = {
theme: "dark",
volume: 80
};
2οΈβ£ Pick and Omit: The Selector Tools
π― Pick - Choose What You Want
Like picking toppings for your pizza!
type Product = {
id: number;
name: string;
price: number;
description: string;
};
// I only want id and name
type ProductPreview = Pick<Product,
"id" | "name"
>;
const preview: ProductPreview = {
id: 1,
name: "Toy Car"
};
βοΈ Omit - Remove What You Donβt Want
The opposite of Pick. Throw away what you donβt need!
// Remove the description
type ProductCard = Omit<Product,
"description"
>;
const card: ProductCard = {
id: 1,
name: "Toy Car",
price: 19.99
};
graph TD A["Full Type"] --> B{What do you need?} B -->|Keep specific fields| C["Use Pick"] B -->|Remove specific fields| D["Use Omit"]
3οΈβ£ Record Type: The Dictionary Maker
Think of a phone book: names β phone numbers.
// Create a dictionary type
type Scores = Record<string, number>;
const gameScores: Scores = {
"Alice": 100,
"Bob": 85,
"Charlie": 92
};
You can use specific keys too:
type Role = "admin" | "user" | "guest";
type Permissions = Record<Role, boolean>;
const access: Permissions = {
admin: true,
user: true,
guest: false
};
4οΈβ£ Exclude and Extract: The Filter Twins
π« Exclude - Remove Types
Like filtering out candies you donβt like!
type AllColors = "red" | "blue" | "green";
// Remove "red" from the options
type CoolColors = Exclude<AllColors, "red">;
// Result: "blue" | "green"
β Extract - Keep Only Matching Types
Keep only the candies you love!
type Numbers = 1 | 2 | "a" | "b";
// Keep only the numbers
type OnlyNumbers = Extract<Numbers, number>;
// Result: 1 | 2
graph TD A["Union Type"] --> B{Filter how?} B -->|Remove matching| C["Exclude"] B -->|Keep matching| D["Extract"]
5οΈβ£ NonNullable: The Safety Guard
Removes null and undefined from a type.
type MaybeString = string | null | undefined;
// Remove the scary nulls!
type SafeString = NonNullable<MaybeString>;
// Result: string
const name: SafeString = "Hello"; // β
// const bad: SafeString = null; // β Error!
Why use it? Prevents those annoying βcannot read property of nullβ errors!
6οΈβ£ ReturnType and Parameters: The Function Inspectors
π ReturnType - What Does It Give Back?
Peek at what a function returns!
function getUser() {
return {
id: 1,
name: "Sam"
};
}
type UserResult = ReturnType<typeof getUser>;
// Result: { id: number; name: string }
π₯ Parameters - What Does It Take In?
See what arguments a function needs!
function greet(name: string, age: number) {
return `Hi ${name}, you are ${age}`;
}
type GreetArgs = Parameters<typeof greet>;
// Result: [string, number]
7οΈβ£ Awaited Type: The Promise Unwrapper
Promises are like gift boxes. Awaited opens them!
type WrappedNumber = Promise<number>;
// Unwrap the promise
type JustNumber = Awaited<WrappedNumber>;
// Result: number
Works with nested promises too:
type DeepPromise = Promise<Promise<string>>;
type UnwrappedValue = Awaited<DeepPromise>;
// Result: string (fully unwrapped!)
8οΈβ£ String Manipulation Types: Text Transformers
TypeScript can transform strings at the type level!
π’ Uppercase & Lowercase
type Shout = Uppercase<"hello">;
// Result: "HELLO"
type Whisper = Lowercase<"HELLO">;
// Result: "hello"
π© Capitalize & Uncapitalize
type Proper = Capitalize<"john">;
// Result: "John"
type Lower = Uncapitalize<"Hello">;
// Result: "hello"
π¨ Real-World Example
type EventName = "click" | "hover";
type Handler = `on${Capitalize<EventName>}`;
// Result: "onClick" | "onHover"
πͺ The Big Picture
graph TD A["Utility Types"] --> B["Object Shapers"] A --> C["Union Filters"] A --> D["Function Tools"] A --> E["String Magic"] B --> B1["Partial"] B --> B2["Required"] B --> B3["Pick"] B --> B4["Omit"] B --> B5["Record"] C --> C1["Exclude"] C --> C2["Extract"] C --> C3["NonNullable"] D --> D1["ReturnType"] D --> D2["Parameters"] D --> D3["Awaited"] E --> E1["Uppercase"] E --> E2["Lowercase"] E --> E3["Capitalize"] E --> E4["Uncapitalize"]
π Quick Summary
| Tool | What It Does | When to Use |
|---|---|---|
Partial<T> |
All fields optional | Update forms |
Required<T> |
All fields required | Strict configs |
Pick<T, K> |
Keep some fields | API responses |
Omit<T, K> |
Remove some fields | Hide sensitive data |
Record<K, V> |
Create dictionaries | Key-value maps |
Exclude<T, U> |
Remove from union | Filter options |
Extract<T, U> |
Keep from union | Select matching |
NonNullable<T> |
Remove null/undefined | Safety first! |
ReturnType<F> |
Get return type | Match function output |
Parameters<F> |
Get argument types | Match function input |
Awaited<T> |
Unwrap promises | Async values |
Uppercase<S> |
MAKE IT LOUD | String constants |
Lowercase<S> |
make it quiet | Normalization |
Capitalize<S> |
First letter big | Formatting |
Uncapitalize<S> |
first letter small | Formatting |
π You Did It!
You now have a magical toolbox of utility types! Each one transforms types in a specific way, saving you from writing repetitive code.
Remember:
- π Partial = make optional
- π Required = make mandatory
- π― Pick = choose fields
- βοΈ Omit = remove fields
- π Record = create dictionaries
- π« Exclude = filter out
- β Extract = filter in
- π‘οΈ NonNullable = remove nulls
- π ReturnType = what it returns
- π₯ Parameters = what it takes
- π¦ Awaited = unwrap promises
- π€ String types = transform text
Youβre now a TypeScript Utility Type wizard! π§ββοΈβ¨
