The JavaScript problem
I started with JavaScript like most web developers. It was fine for small scripts, but as my projects grew, things started falling apart:
- Functions receiving unexpected
undefinedvalues - Typos in property names causing silent bugs
- Refactoring becoming terrifying
Sound familiar?
The switch
I resisted TypeScript for a while. "Too verbose", "slows me down", "I know my code". Classic excuses.
Then I spent 3 hours debugging a bug that TypeScript would have caught in 3 seconds:
// The bug: user.name was sometimes undefined
// JavaScript: silently fails, shows "undefined" in the UI
// TypeScript: yells at you immediately
type User = {
id: string;
name: string;
email: string;
};
function greet(user: User) {
return `Hello, ${user.name}!`;
// TypeScript guarantees user.name exists
}That was it. I switched and never looked back.
What TypeScript actually gives you
1. Autocomplete everywhere
Your editor becomes incredibly smart. It knows every property, every method, every return type. You stop guessing and start flowing.
2. Refactoring confidence
Rename a type, and every usage lights up. Change a function signature, and TypeScript tells you every call site that needs updating. No more "find and replace and pray".
3. Self-documenting code
Types ARE documentation. When I read this:
async function createPost(
data: Pick<BlogPost, "title" | "description" | "date">
): Promise<BlogPost> {
// ...
}I immediately know what it takes and what it returns. No JSDoc needed.
4. Catching bugs at compile time
The TypeScript compiler catches entire categories of bugs:
- Null/undefined access
- Missing properties
- Wrong argument types
- Unreachable code
Tips for getting started
If you're still on the fence:
- Start with
strict: true— it's tempting to be lenient, but strict mode is where the real value is - Use
unknownoverany—anydefeats the purpose of TypeScript - Let inference work — you don't need to annotate everything, TypeScript is smart
- Learn utility types —
Partial,Pick,Omit,Recordsave tons of boilerplate
My config
Here's the tsconfig.json base I use for every project:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}noUncheckedIndexedAccess is an underrated gem — it forces you to handle the case where an array index or object key might not exist.
The verdict
TypeScript isn't just about catching bugs. It's about thinking more clearly about your code. Types force you to define your data shapes upfront, which leads to better architecture.
Is it perfect? No. Generics can get wild, and some library types are a mess. But the tradeoff is overwhelmingly worth it.