Catching Typos in TypeScript: Automatically Correcting Common Mistakes with Mapped Types
In a world where developers work across multiple teams and languages, it’s not uncommon to encounter consistent typos in data structures—especially when backend developers define API objects with misspelled property names. One classic example? The infamous misspelling of "parms"
instead of "params"
. While it’s a small slip, it can create a lot of friction in a TypeScript project, especially when your frontend code expects correctly named properties.
But instead of chasing these typos across your entire codebase, TypeScript’s mapped types offer a brilliant solution.
Understanding Mapped Types
A mapped type in TypeScript lets you create new types by transforming the keys and values of an existing type. Think of it as a way to apply a function over the keys of an object, allowing you to:
- Rename properties based on a condition.
- Change value types.
- Filter out certain properties.
- Even recursively map nested objects.
Here’s a simple example that transforms one property name:
type ParamsToParms<T> = {
[K in keyof T as K extends "parms" ? "params" : K]: T[K];
};
This type does the following:
- Iterates over all keys
K
in the input typeT
. - If a key is exactly
"parms"
, it gets renamed to"params"
. - If not, the key stays the same.
- The value type for each key remains unchanged.
Why This Trick is Hilarious (and Practical)
The humor comes from how elegant yet simple this solution is. Instead of arguing with your backend team or manually fixing misspelled keys, you can simply let TypeScript handle it for you. It’s a clever hack that feels like it’s “cheating,” but it actually leverages TypeScript’s strengths perfectly.
Here’s an example:
type Example = {
foo: string;
readonly parms: string;
};
type FixedExample = ParamsToParms<Example>;
FixedExample
automatically becomes:
{
foo: string;
readonly params: string;
}
Beyond "parms": Generalizing the Approach
This mapped type isn’t limited to just one typo. You can expand the logic to correct multiple common mistakes:
type RenameKeys<T> = {
[K in keyof T as K extends "parms" ? "params" :
K extends "usrname" ? "username" :
K extends "emial" ? "email" :
K]: T[K];
};
This will correct:
"parms"
to"params"
"usrname"
to"username"
"emial"
to"email"
You can extend this list as needed, especially in projects where you know common naming issues will crop up.
Considering Deep Nesting
What if these misspelled keys appear inside nested objects? You can create a recursive mapped type to drill down into the object structure:
type DeepRename<T> = {
[K in keyof T as K extends "parms" ? "params" :
K extends "usrname" ? "username" :
K]: T[K] extends object ? DeepRename<T[K]> : T[K];
};
Now, even deeply nested properties will get corrected automatically. This is invaluable in large APIs where typos might appear in nested data.
Considerations and Limitations
While this approach is powerful, there are important considerations:
- Type Safety vs Runtime: These transformations happen at compile-time only. If your backend still sends the misspelled key (
parms
), the actual JavaScript object will still have the typo unless you also transform the data at runtime. - Avoid Overcorrection: Be cautious not to accidentally rename properties that are valid. For example, if someone genuinely intended
"parms"
, this type will still rename it. - API Evolution: This technique is great for patching inconsistent APIs temporarily, but the best solution is always to fix the source data.
- Performance: There’s no performance penalty at runtime because TypeScript’s type system is erased during compilation. However, overly complex recursive types can slow down type checking in large projects.
Final Thoughts
This hilarious and surprisingly effective technique highlights how TypeScript’s type system can go beyond just “type checking”—it can actually transform your data model to adapt to human mistakes. Whether you’re battling the "parms"
typo or any other repeated misspelling, mapped types offer an elegant, maintainable solution.
So next time your backend team ships an API with "parms"
, don’t worry—TypeScript’s got your back.
Comments ()