Why TypeScript Made Me Rewrite My Favorite Utility Functions
Like most developers, I’ve been collecting utility functions for years — little helpers for cloning objects, checking types, validating inputs, and cleaning up code.
I trusted them. I reused them. I shipped them in production.
Then I started using TypeScript seriously.
And suddenly, my beloved helpers started falling apart.
This post is about how TypeScript didn’t just improve my JavaScript — it challenged it. It made me rewrite some of my most “reliable” code.
🧪 Utility #1: deepClone()
Old version:
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}It worked… until it didn’t:
- Lost dates
- Dropped undefined values
- Couldn’t clone functions
TypeScript flagged it:
function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj)); // ⚠️ Not safe for all types
}Even though we typed it as generic T, TypeScript couldn’t guarantee that the returned value had all the right nested types preserved.
Rewrite with structured clone:
function deepClone<T>(value: T): T {
return structuredClone(value); // ✅ built-in, type-safe
}Now it’s native, cleaner, and keeps the type integrity — no weird surprises with dates or nested objects.
🤷♂️ Utility #2: isEmpty()
Old version:
function isEmpty(value) {
return (
value == null ||
(typeof value === 'string' && value.trim() === '') ||
(Array.isArray(value) && value.length === 0)
);
}Works in JS. But:
nullandundefinedare ambiguous- It accepts any input — no clarity
- Hard to trust in large apps
TypeScript rewrite:
function isEmpty(value: string | any[] | null | undefined): boolean {
if (value == null) return true;
if (typeof value === 'string') return value.trim() === '';
if (Array.isArray(value)) return value.length === 0;
return false;
}Now:
- Types are clear
- Logic is predictable
- Safer in large codebases
Bonus: TypeScript warns me if I try to pass an unsupported type like an object or number.
💡 Utility #3: toTitleCase()
Old version:
function toTitleCase(str) {
return str.replace(/\b\w/g, c => c.toUpperCase());
}No checks, no types, and breaks if null is passed.
Get Kavindu Kokila (Kavi Castelo)’s stories in your inbox
Join Medium for free to get updates from this writer.
TypeScript rewrite:
function toTitleCase(str: string): string {
return str.replace(/\b\w/g, (c) => c.toUpperCase());
}Now it only accepts a valid string. Any mistake is caught before runtime.
🛑 Utility #4: getProp(obj, path)
Old version:
function getProp(obj, path) {
return path.split('.').reduce((acc, key) => acc?.[key], obj);
}It works… but with no guarantees:
- Path can be anything
- Return value could be
undefined,null, or an error - No type safety
TypeScript rewrite:
function getProp<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}If you’re using dot-paths, it gets trickier — but even a basic keyof rewrite is miles safer than the untyped dynamic string version.
🧪 Utility #5: mergeDefaults()
Old version:
function mergeDefaults(obj, defaults) {
return { ...defaults, ...obj };
}This was fine for shallow merges. But it had problems:
- Didn’t alert on type mismatches
- Could silently overwrite values
TypeScript rewrite:
function mergeDefaults<T extends object, U extends Partial<T>>(obj: U, defaults: T): T {
return { ...defaults, ...obj };
}Now TypeScript checks:
- That
objis assignable toT - That you’re not introducing invalid keys
📦 What I Learned
TypeScript made me face a hard truth: most of my JS utilities were based on assumptions. Implicit conversions, loose types, silent failures — all hidden under the surface.
When I added TypeScript:
- Some of them broke
- Others revealed edge cases
- A few became unnecessary (because TypeScript solved the problem by design)
But in the process, I wrote better code. More explicit, more testable, more trustworthy.
🧠 Takeaway
You don’t need to rewrite everything. But try running your old utility file through the TypeScript compiler — and see what survives 😅
If you care about long-term maintainability, clarity, and scale — TypeScript isn’t just a tool.
It’s a second brain.
👉 Got a favorite utility TypeScript made you rethink? Drop it in the comments or tweet me your story.
Thank you for being a part of the community
Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: X | LinkedIn | YouTube | Newsletter | Podcast | Twitch
- Start your own free AI-powered blog on Differ 🚀
- Join our content creators community on Discord 🧑🏻💻
- For more content, visit plainenglish.io + stackademic.com











