TypeScript
TypeScript Best Practices and Design Patterns
•12 min read

Mahmoud Amr

TypeScript Best Practices and Design Patterns
Learn how to write clean, type-safe TypeScript code using modern design patterns and best practices.
Type System Fundamentals
Advanced Types
Using utility types effectively:
type User = {
id: number;
name: string;
email: string;
settings: {
theme: 'light' | 'dark';
notifications: boolean;
};
};
// Pick specific properties
type UserBasics = Pick<User, 'id' | 'name'>;
// Make properties optional
type PartialUser = Partial<User>;
// Make properties required
type RequiredUser = Required<User>;
// Extract union type
type Theme = Extract<User['settings']['theme'], string>;
Generic Constraints
Creating flexible, type-safe functions:
interface HasId {
id: number | string;
}
function findById<T extends HasId>(items: T[], id: T['id']): T | undefined {
return items.find(item => item.id === id);
}
// Usage
const users: User[] = [/* ... */];
const user = findById(users, 1);
Design Patterns
The Builder Pattern
Type-safe builder implementation:
class RequestBuilder {
private config: RequestInit = {};
setMethod(method: 'GET' | 'POST' | 'PUT' | 'DELETE'): this {
this.config.method = method;
return this;
}
setHeaders(headers: HeadersInit): this {
this.config.headers = headers;
return this;
}
setBody<T>(body: T): this {
this.config.body = JSON.stringify(body);
return this;
}
build(): RequestInit {
return this.config;
}
}
// Usage
const request = new RequestBuilder()
.setMethod('POST')
.setHeaders({ 'Content-Type': 'application/json' })
.setBody({ data: 'example' })
.build();
Error Handling
Type-safe error handling:
class AppError extends Error {
constructor(
message: string,
public code: number,
public details?: Record<string, unknown>
) {
super(message);
this.name = 'AppError';
}
}
function handleError(error: unknown): void {
if (error instanceof AppError) {
console.error(`[${error.code}] ${error.message}`);
if (error.details) {
console.error('Details:', error.details);
}
} else {
console.error('Unknown error:', error);
}
}
Best Practices
- Use strict compiler options
- Leverage type inference
- Implement proper error handling
- Write self-documenting code
- Use discriminated unions
Conclusion
Following these TypeScript best practices will help you write more maintainable and type-safe applications.
TypeScriptJavaScriptWeb DevelopmentProgramming