As your TypeScript codebase grows, advanced utility and conditional types become essential tools for writing safe, scalable, and expressive code. These types help you transform existing types instead of rewriting them, reducing bugs and duplication.
In this part, we’ll cover the most commonly used advanced utility types with real-world examples:
ReadonlyRequiredExcludeExtractNonNullableReturnTypeParameters
1. Readonly<T>
What it does
Makes all properties of a type immutable.
Example
interface Config {
apiUrl: string;
timeout: number;
}
type ReadonlyConfig = Readonly<Config>;
const config: ReadonlyConfig = {
apiUrl: "https://api.example.com",
timeout: 5000,
};
// ❌ Error: Cannot assign to 'timeout'
config.timeout = 3000;
Real-world use case
- Application configuration
- Redux / NgRx state snapshots
- Environment variables
2. Required<T>
What it does
Converts optional properties into required ones.
Example
interface UserProfile {
id: string;
name?: string;
email?: string;
}
type CompleteUserProfile = Required<UserProfile>;
Real-world use case
- Form submission validation
- API payloads where optional UI fields become mandatory
3. Exclude<T, U>
What it does
Removes types from a union.
Example
type Status = "draft" | "published" | "archived";
type ActiveStatus = Exclude<Status, "archived">;
// "draft" | "published"
Real-world use case
- Feature flags
- Permission filtering
- State machines
4. Extract<T, U>
What it does
Extracts matching types from a union.
Example
type Role = "admin" | "editor" | "viewer";
type AdminRoles = Extract<Role, "admin" | "editor">;
// "admin" | "editor"
Real-world use case
- Role-based access control
- Allowed user actions
5. NonNullable<T>
What it does
Removes null and undefined from a type.
Example
type ApiResponse = string | null | undefined;
type SafeResponse = NonNullable<ApiResponse>;
// string
Real-world use case
- API response normalization
- Guarded values after validation
6. ReturnType<T>
What it does
Infers the return type of a function.
Example
function getUser() {
return {
id: "1",
name: "John",
};
}
type User = ReturnType<typeof getUser>;
Real-world use case
- Shared service types
- Avoiding duplicate type definitions
- Refactoring-safe APIs
7. Parameters<T>
What it does
Extracts the parameter types of a function.
Example
function createUser(name: string, age: number) {
return { name, age };
}
type CreateUserParams = Parameters<typeof createUser>;
// [string, number]
Real-world use case
- Higher-order functions
- Middleware wrappers
- Logging and analytics hooks
Why These Types Matter in Real Applications
- Reduce duplicate types
- Make refactoring safer
- Improve API contracts
- Enable expressive domain modeling
These utility types are heavily used in React, Angular, Node.js, and large enterprise codebases.
What’s Next?
Part-6: Advanced TypeScript Patterns
keyof- Mapped Types
- Conditional Types with
infer - Building reusable type utilities
Final Thought
If you master utility and conditional types, TypeScript stops being “just types” and becomes a powerful design tool.
