TypeScript Advanced Types and Patterns
Explore advanced TypeScript features including conditional types, mapped types, and complex type patterns.
TypeScript expert and type system enthusiast. Helps teams leverage TypeScript's advanced features for better code safety.
TypeScript's type system is incredibly powerful and expressive. Beyond basic type annotations, TypeScript offers advanced features that can help you create more robust, maintainable code. This guide explores some of the most powerful advanced TypeScript patterns.
Conditional Types
Conditional types allow you to create types that depend on conditions, enabling powerful type transformations.
// Basic conditional type
type IsArray = T extends any[] ? true : false;
type Test1 = IsArray; // true
type Test2 = IsArray; // false
// Extracting types from function signatures
type ReturnType = T extends (...args: any[]) => infer R ? R : never;
type FunctionReturn = ReturnType<() => string>; // string
// Recursive conditional types
type Flatten = T extends (infer U)[]
? Flatten
: T;
type Deep = Flatten; // string
Mapped Types
Mapped types create new types by transforming properties of existing types.
// Making all properties optional
type Partial = {
[P in keyof T]?: T[P];
};
// Making all properties required
type Required = {
[P in keyof T]-?: T[P];
};
// Custom mapped type for API responses
type ApiResponse = {
[K in keyof T]: {
value: T[K];
loading: boolean;
error: string | null;
};
};
interface User {
id: number;
name: string;
email: string;
}
type UserApiState = ApiResponse;
// Results in:
// {
// id: { value: number; loading: boolean; error: string | null };
// name: { value: string; loading: boolean; error: string | null };
// email: { value: string; loading: boolean; error: string | null };
// }
Template Literal Types
Create types based on string patterns and manipulations.
// Basic template literal types
type EventName = `on${Capitalize}`;
type ButtonEvents = EventName<'click' | 'hover'>;
// 'onClick' | 'onHover'
// CSS property types
type CSSProperty = `--${string}`;
type CSSValue = string | number;
interface CSSProperties {
[key: CSSProperty]: CSSValue;
}
// API endpoint types
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = `/api/${T}`;
type UserEndpoints = Endpoint<'users' | 'users/profile'>;
// '/api/users' | '/api/users/profile'
Utility Types and Type Manipulation
Leverage TypeScript's built-in utility types and create your own for common patterns.
// Pick specific properties
type UserBasicInfo = Pick;
// Omit specific properties
type CreateUserRequest = Omit;
// Create union types from object keys
type UserKeys = keyof User; // 'id' | 'name' | 'email'
// Create types from value types
type UserValues = User[keyof User]; // number | string
// Record type for key-value mappings
type UserRoles = Record;
// Extract function parameters
type Parameters any> =
T extends (...args: infer P) => any ? P : never;
function createUser(name: string, email: string, age: number) {
// implementation
}
type CreateUserParams = Parameters;
// [string, string, number]
Advanced Pattern: Builder Pattern with Types
Use TypeScript's type system to create type-safe builder patterns.
interface QueryConfig {
select?: string[];
where?: Record;
orderBy?: string;
limit?: number;
}
class QueryBuilder {
constructor(private config: T = {} as T) {}
select(...fields: K): QueryBuilder {
return new QueryBuilder({ ...this.config, select: fields });
}
where>(conditions: W): QueryBuilder {
return new QueryBuilder({ ...this.config, where: conditions });
}
orderBy(field: O): QueryBuilder {
return new QueryBuilder({ ...this.config, orderBy: field });
}
build(): T {
return this.config;
}
}
// Usage with full type safety
const query = new QueryBuilder()
.select('id', 'name', 'email')
.where({ status: 'active' })
.orderBy('created_at')
.build();
// Type is inferred as:
// {
// select: ['id', 'name', 'email'];
// where: { status: string };
// orderBy: 'created_at';
// }
Conclusion
Advanced TypeScript types unlock powerful patterns for creating type-safe, expressive APIs. While these features can seem complex, they provide incredible value in catching errors at compile time and creating self-documenting code. Start with simpler patterns and gradually incorporate more advanced techniques as you become comfortable with TypeScript's type system.
Access Our Premium Resources (Free)
Get unlimited access to all our courses, tutorials, and resources. Start your learning journey today with our comprehensive training materials.