TypeScript has evolved significantly. Here are the best practices for writing modern TypeScript code in 2025.
Always enable strict mode in your tsconfig.json
:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
}
Let TypeScript infer types when obvious:
// ❌ Overly explicit
const name: string = "John"
const numbers: number[] = [1, 2, 3]
// ✅ Let TypeScript infer
const name = "John"
const numbers = [1, 2, 3]
For object shapes, interfaces are more performant:
// ✅ Good
interface User {
id: string
name: string
email: string
}
// Use type aliases for unions and intersections
type Status = "pending" | "active" | "inactive"
TypeScript provides powerful utility types:
interface User {
id: string
name: string
email: string
password: string
}
// Create variations easily
type PublicUser = Omit<User, "password">
type PartialUser = Partial<User>
type ReadonlyUser = Readonly<User>
any
TypeInstead of any
, use unknown
for truly unknown types:
// ❌ Avoid
function processData(data: any) {
// No type safety
}
// ✅ Better
function processData(data: unknown) {
// Must validate before use
if (typeof data === 'string') {
console.log(data.toUpperCase())
}
}
For literal types and readonly objects:
// Literal type
const config = {
api: "https://api.example.com",
timeout: 5000
} as const
// Array of literals
const colors = ["red", "green", "blue"] as const
type Color = typeof colors[number] // "red" | "green" | "blue"
TypeScript is more than just "JavaScript with types". By following these practices, you'll write more maintainable, self-documenting code that catches errors before they reach production.