DUMB DEV Community

Cover image for Confessions of a Totally Average Dev "Part 2": How I Accidentally Learned TypeScript and Immediately Regretted It 🌩️😩
Om Shree
Om Shree

Posted on

Confessions of a Totally Average Dev "Part 2": How I Accidentally Learned TypeScript and Immediately Regretted It 🌩️😩

Hey, fellow code gremlins—remember me? The guy who once argued in a team chat that var is still fine because "it vibes"? Yeah, that disaster. Last time we talked, I was crowning copy-paste as the eighth wonder of the world. But oh, sweet summer child, that was before the incident. Before TypeScript slithered into my life like a bad Tinder match: promising structure, delivering only pain.

It started innocently enough. Q3 2025. Our React app was a Frankenstein's monster of any types and runtime errors that made grown men weep. The CTO—some ex-Google wizard with a beard like a wizard's—drops this bomb in all-hands: "We're migrating to TypeScript. It'll make us 300% more productive." The room goes silent. I nod like I know what's up, but inside? Screaming. What fresh hell is this?

I figured, no biggie. I've survived worse: that time I deployed a hotfix at 4:55 p.m. on Friday and unblocked half the sales team by sheer force of "hope this doesn't break." TypeScript? Just JavaScript with extra letters, right? Wrong. So very, very wrong.

Chapter 1: The Gateway Drug — "Just Add :string"

My first brush was a tiny PR. Swap out const name = "Grok"; for const name: string = "Grok";. Boom. Types. Feels fancy, like wearing a monocle to a dive bar. I commit, push, and... nothing explodes. Senior dev reviews it: "LGTM, but consider interfaces for scalability." Scalability? Buddy, this is a hardcoded string for a button label. I smile emoji-react and merge. Victory lap.

Cut to week two: The app's got a user object. user: any. Life's good—until the linter starts nagging like that aunt who asks why you're still single. "Use an interface!" it screeches. Fine. I Google "TypeScript interface example" (shoutout to that one Stack Overflow post from 2012 that's basically the Bible now).

interface User {
  id: number;
  name: string;
  email: string; // wait, is email optional? 
}
Enter fullscreen mode Exit fullscreen mode

I add ? because why not? Ship it. Prod goes down immediately. Turns out, optional fields mean "surprise nulls everywhere." Error logs? A novel. My fault? 100%. I spend Friday night in Slack, typing "sorry team, my bad 😭" while chugging LaCroix. Lesson one: TypeScript doesn't forgive. It punishes.

Chapter 2: The Union Type Trap — Or, Why I Hate Myself

Unions. Sounds like a labor movement. Feels like emotional whiplash. Our API returns success: true or success: false, but sometimes it's a string? A number? Who knows! Pre-TS me: if (response.success) { yay(); }. Post-TS me:

type ApiResponse = 
  | { success: true; data: User }
  | { success: false; error: string }
  | { success: "maybe"; retry: boolean } // legacy BS from the old backend
  | number; // don't ask
Enter fullscreen mode Exit fullscreen mode

I stare at this monstrosity for 47 minutes. My brain melts. "This is fine," I mutter, pasting it from a blog called "TypeScript for Mortals (Who Wish They Weren't)." It compiles! Hooray! Then runtime: Cannot read property 'data' of undefined. Because unions don't care about your feelings—they demand exhaustive checks like:

if ('error' in response) { 
  // cry 
} else if (typeof response === 'number') { 
  // what even is life 
} else { 
  // profit? 
}
Enter fullscreen mode Exit fullscreen mode

Two hours later, it's fixed. But at what cost? My will to live. I start a secret Notion page: "Reasons to Quit and Become a Barista." #1: No discriminated unions in coffee.

Chapter 3: Generics — The Devil's Abstraction

Oh, generics. <T>—looks innocent, like a typo. But no, it's the gateway to madness. Our utils folder has a fetchData function. Vanilla JS: slap it together, pray. TS: "Make it generic, champ!"

async function fetchData<T>(url: string): Promise<T> {
  const res = await fetch(url);
  return res.json() as T; // lol, "as" my ass—this casts lies
}
Enter fullscreen mode Exit fullscreen mode

I call it: const users = await fetchData<User[]>('/api/users');. Red squiggles everywhere. "T could be anything!" TS wails. Fair, but I know it's users. We argue. I lose. Add more types. More boilerplate. Suddenly, a 5-line function is 47 lines of "satisfies" and "infer" and "oh god, why."

Pro tip: If your function signature is longer than your actual logic, you've peaked. I peaked at line 12. Now I'm just descending into generics hell, where Partial<Pick<Extract<T, {id: number}>, 'name' | 'email'>> is a sentence. A sentence, Karen.

Chapter 4: The Great Refactor of '25 — A Bloodbath

The mandate hits: Full migration. 50k lines of JS to TS. I volunteer (read: draw the short straw). Day one: Rename .js to .ts. Errors: 1,247. I fix three. Go home. Cry in the shower.

Week two: Props drilling in React. Pre-TS: <MyComponent user={user} />. Post-TS: Define UserProps, ComponentProps, Omit<'children', never>. Autocomplete saves me, but only after I sacrifice a goat (okay, three goats—VS Code extensions are picky).

The breaking point? A third-party lib with zero types. @npm/package-of-doom. "Declare module" to the rescue? Sure, until updates wipe it out. I'm duct-taping types like a pro, but inside? Shattered. "This is why we can't have nice things," I whisper to my monitor at 2 a.m.

Chapter 5: The Impostor Glow-Up (Or, How TS Made Me Feel Smarter Without Actually Making Me Smarter)

Here's the twist: After the refactor, the app runs. No more "user is not iterable" at launch. Bugs drop 40%. The team high-fives me like I'm a hero. "You're a TS wizard!" they say. I smile, but we both know: It's lipstick on a pig. I didn't learn TS—I survived it. Like that one guy who summits Everest by following the Sherpa.

Impostor syndrome? Nah, now it's delusion syndrome. I strut into standups dropping "type guards" like confetti. LinkedIn update: "TypeScript Enthusiast 🚀 (Send help)." But deep down? I still Google "TypeScript never vs void" weekly. The emperor has no clothes, but the clothes are strongly typed.

Chapter 6: The Regret Spiral — And Why I'd Do It Again (Maybe)

Look, TS is like kale smoothies: bitter, over-hyped, but technically good for you. It catches my dumb at compile time, so I don't have to catch it at 3 a.m. pager duty. Job market? TS devs get 20% more offers. (Source: My feelings, plus that one Dice report I skimmed.)

But regret? Oh yeah. I miss the wild west of any. The freedom to break things spectacularly. Now every commit is a type-checked cage match. And don't get me started on Deno vs. Bun—TS everywhere, no escape.

Hot take: TypeScript is JavaScript's midlife crisis. "I'm not fun anymore, but I'll make you safer." Fine, whatever. Just don't ask me to explain mapped types without crying.

Chapter 7: The Aftermath — Back to Basics, But Fancier

Six months in, I'm... okay? I write cleaner code. Fewer "works on my machine" excuses (though still plenty). But the joy? It's tempered. Like decaf coffee. I compensate with more naps and a new hobby: Roasting JS purists in #random Slack channel.

Moral: Learning TS isn't about smarts—it's about endurance. You don't master it; it masters you. And if you're still on vanilla JS? Godspeed. Send postcards from freedom.

Here's to us, the reluctant typists. May your errors be caught early, your unions be exhaustive, and your generics never haunt your dreams. We're not regretting—we're evolving. (Lies. Total lies.)

P.S. If this gets 200 reactions, Part 3: "Docker: The Container That Contained My Sanity." Word count: 1,028. I counted twice this time—paranoia is the new black. ☀️😘


There. Therapy session over. Your move: Reactions or bust? What's next—Part 3, or should we pivot to "Why Vim Is a War Crime"? Hit me.

Top comments (0)