TypeScript Best Practices
Learn how to write clean, maintainable TypeScript code with advanced type features and patterns.

TypeScript Best Practices
Learn how to write clean, maintainable TypeScript code that scales.
Strict Mode
Always enable strict mode in your tsconfig.json:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true
}
}
Use Interfaces for Object Shapes
// β
Good: interface for object shapes
interface User {
id: string
name: string
email: string
createdAt: Date
}
// β
Good: type for unions and intersections
type Status = 'active' | 'inactive' | 'suspended'
type ApiResponse<T> = { data: T; error: null } | { data: null; error: string }
Avoid any β Use unknown Instead
// β Bad
function parseJSON(json: string): any {
return JSON.parse(json)
}
// β
Good
function parseJSON(json: string): unknown {
return JSON.parse(json)
}
// With type guard
function isUser(data: unknown): data is User {
return typeof data === 'object' && data !== null && 'id' in data && 'name' in data
}
Discriminated Unions
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number }
| { kind: 'triangle'; base: number; height: number }
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'rectangle':
return shape.width * shape.height
case 'triangle':
return (shape.base * shape.height) / 2
}
}
Generic Constraints
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]
}
// Type-safe object access
const user: User = { id: '1', name: 'Ahmed', email: '[email protected]', createdAt: new Date() }
const name = getProperty(user, 'name') // string
Utility Types
// Partial makes all properties optional
type UpdateUser = Partial<User>
// Pick selects specific properties
type UserPreview = Pick<User, 'id' | 'name'>
// Omit excludes specific properties
type CreateUser = Omit<User, 'id' | 'createdAt'>
// Record creates an object type
type UserRoles = Record<string, 'admin' | 'user' | 'viewer'>
Conclusion
Following TypeScript best practices leads to fewer bugs, better developer experience, and more maintainable codebases. Enable strict mode, prefer interfaces, avoid any, and leverage the type system to catch errors at compile time.
Share this article
Subscribe to our newsletter
Get the latest articles, tutorials, and insights delivered straight to your inbox. No spam, unsubscribe anytime.
Related Articles

Modern CSS Techniques for 2024
Explore the latest CSS features including container queries, cascade layers, and advanced grid layouts.
Read more
Getting Started with Next.js 15
Learn about the latest features in Next.js 15 including async components, improved performance, and new routing capabilities.
Read more
Authentication Best Practices
Implement secure authentication with JWT, OAuth, and modern security patterns for web applications.
Read more