TypeScript Best Practices for Large Codebases
TypeScript brings safety and scalability to JavaScript. But with great power comes great responsibility. Here are some hard-won lessons.
π§Ό 1. Prefer type over interface
// β
Better
type User = {
id: number;
name: string;
};
// β Avoid when not extending
interface User {
id: number;
name: string;
}
Use type for union, intersection, and readability.
π 2. Modularize Types
Avoid a types.ts god file. Instead:
- Co-locate types with domain logic
- Export them from index if needed
// user/types.ts
export type User = { id: number; name: string };
// user/index.ts
export * from "./types";
π§ͺ 3. Use Narrow Types
Instead of generic types:
// β
function log(level: string) {}
// β
type LogLevel = "info" | "warn" | "error";
function log(level: LogLevel) {}
π 4. Enforce strict mode
Enable in tsconfig.json:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true
}
}
This avoids silent type issues.
π 5. Document Complex Types
/**
* Represents a GitHub API user payload
*/
type GitHubUser = {
login: string;
id: number;
avatar_url: string;
};
π§ Final Thoughts
TypeScript doesnβt just catch bugs β it also documents intent.
π Recommended Tools
- ESLint with
@typescript-eslint - TypeDoc
- ts-prune (find unused types)