Let’s face it — we’ve all been there. Staring at a red squiggly line in our IDE, whispering “just this once,” and slapping an any
on a variable like duct tape on a leaky pipe.
But TypeScript deserves better. You deserve better. So buckle up, because I’m about to share 12 TypeScript best practices that will make your code cleaner, safer, and dare I say… elegant?
1. ❌ Avoid any
Like It’s on Fire
If you use
any
, you’re just writing JavaScript with extra steps. – Probably someone wise
Instead of:
function processData(data: any) {
console.log(data.name);
}
Use:
function processData(data: { name: string }) {
console.log(data.name);
}
🧠 Tip: If you must use something flexible, try unknown
or generics instead of any
.
2. ✅ Prefer type
or interface
, But Be Consistent
Both are valid! Use interface
for object shapes you expect to extend, and type
for unions or function signatures.
interface User {
name: string;
age: number;
}
type ResponseStatus = 'success' | 'error';
🚨 Mixing them randomly? That’s the TypeScript equivalent of putting ketchup on spaghetti.
3. 💡 Use Type Inference, but Don’t Over-rely
TypeScript is smart. Let it infer when it can, but explicit is better than implicit for exported values and public APIs.
const name = 'Alice'; // okay to infer
export const MAX_RETRIES: number = 5; // better to be explicit
4. 🛑 Never Ignore the Compiler
You know that red error? It’s not a suggestion, it’s a cry for help.
Fix. Your. Types.
5. 📦 Use Readonly
, Partial
, Pick
, and Record
These utility types are like magical Lego bricks.
type ReadonlyUser = Readonly<User>;
type PartialUser = Partial<User>;
type NameOnly = Pick<User, 'name'>;
type Roles = Record<string, 'admin' | 'user'>;
They make your life easier — embrace them.
6. 🧱 Model Your Data Precisely
Don’t be lazy with types. Use literal types, enums, and unions to model the real world.
Or, if you’re fancy:
enum OrderStatus {
Pending = 'pending',
Shipped = 'shipped',
Cancelled = 'cancelled'
}
7. 🤹♂️ Go Generic — But With Purpose
Generics = flexible but typesafe.
function wrapInArray<T>(value: T): T[] {
return [value];
}
Don’t use <T>
because it looks cool. Use it when your function should work with multiple types.
8. 🔍 Use strict
Mode (Seriously)
Enable this in your tsconfig.json
:
{
"compilerOptions": {
"strict": true
}
}
This is not optional. This is TypeScript on beast mode. You’ll catch bugs before they hatch.
9. 🪓 Narrow Your Types — Guard Them Well
Type guards are your best friends.
function isUser(obj: any): obj is User {
return obj && typeof obj.name === 'string';
}
The more you narrow a type, the less likely it is to blow up in production.
10. 📚 Document Your Types Like an Adult
Types can be self-documenting. But still — use JSDoc or comments when things get gnarly.
/**
* Represents a user's order history.
*/
type OrderHistory = Order[];
11. 📦 Split Types Into Modules
If your types.ts
file is 900 lines long, it’s time for a refactor. Group types by domain or feature for sanity’s sake.
12. 🧪 Don’t Forget to Test Your Types (Yes, Really)
Tools like tsd let you write assertion tests for your type definitions.
Because you shouldn’t ship types you haven’t tested — just like you wouldn’t ship code you haven’t tested. (Right?)
🧠 Final Thoughts
TypeScript isn’t just JavaScript with types — it’s a way to design better code.
And once you get the hang of it, it’s like coding with a safety net… made of lasers.
So go forth, type with confidence, and please — stop any
-ing around.