Use TypeScript as Intended
TypeScript was created to help developers write safer and more maintainable JavaScript. It enforces static typing, catches errors earlier, improves IDE support, and documents intent directly in code. To fully benefit from it, avoid shortcuts and use TypeScript's advanced features as they were designed.
Key practices
anyis prohibited. Useunknownat boundaries, then narrow it down.- Prefer
typefor unions/mapped types;interfacefor extensible object shapes. - Use generics with constraints and defaults. Extract generic helpers instead of duplication.
- Use literal unions or
enumfor closed sets. Centralize labels and helpers. - Enforce exhaustiveness with
neverin discriminated unions.
Discriminated unions
ts
type ApiResponse =
| { status: "success"; data: string }
| { status: "error"; message: string };
function handleResponse(res: ApiResponse) {
switch (res.status) {
case "success":
return res.data;
case "error":
return res.message;
default:
const _exhaustive: never = res;
return _exhaustive;
}
}typeof keyword
ts
const ROLES = ["admin", "editor", "viewer"] as const;
type Role = typeof ROLES[number]; // "admin" | "editor" | "viewer"
function setRole(role: Role) {
// role is strictly validated
}Generics and wildcards
ts
interface BaseResponse<T> {
status: number;
data: T;
}
function fetchResource<T>(url: string): Promise<BaseResponse<T>> {
return fetch(url).then((res) => res.json());
}
// Usage
type User = { id: number; name: string };
const userResponse = fetchResource<User>("/api/user");