Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
TypeScriptJavaScriptJune 24, 20264 min read

TypeScript Data Normalization: Fixing Undefined Errors with Mapped Types

TypeScript data normalization is essential for avoiding runtime errors. Learn how to use Object.fromEntries and mapped types to ensure your objects stay safe.

TypeScriptJavaScriptData NormalizationType SafetyObject.fromEntriesMapped TypesFrontend

I spent three hours debugging a production incident last month because an API response contained a field I assumed was always present. The code crashed silently, returning undefined where a string was expected, eventually causing a UI flicker that cost us a few support tickets. We were doing manual data normalization, and it was a mess of if checks and type assertions that didn't actually guarantee anything.

If you’re tired of chasing "cannot read property of undefined" errors, you need to tighten up how you transform your data. Combining Object.fromEntries with mapped types provides a robust way to enforce TypeScript structure during data normalization.

The Problem with Loose Normalization

We often take raw API responses and "clean" them into a format our components expect. If you use a standard forEach or map loop to build a new object, TypeScript often loses track of the schema.

TYPESCRIPT
// The dangerous way
const rawData = { id: 1, name: CE9178">'Rubel', role: undefined };
const normalized = {};

Object.keys(rawData).forEach(key => {
  if (rawData[key]) {
    normalized[key] = rawData[key];
  }
});

The issue here is that normalized is inferred as any or {}. You lose all type safety the moment you push a property into it. When you try to access normalized.name later, TypeScript won't warn you if the property is missing or if the type shifted during the transformation.

Using Mapped Types for Schema Enforcement

To fix this, we need to leverage mapped types. Mapped types allow us to create a new type based on an existing one, ensuring every key is accounted for. Before I settled on this, I tried using simple interface extensions, but that only works if the source data is static. When data is dynamic, you need a more flexible approach.

If you are interested in how this scales to more complex structures, I’ve previously written about Preventing Runtime Property Errors with TypeScript Mapped Types, which covers the basics of key manipulation.

Here is how we can normalize data while keeping the compiler happy:

TYPESCRIPT
type User = { id: number; name: string; role: string | null };

function normalizeUser(raw: any): User {
  // We define the keys we expect
  const keys: (keyof User)[] = [CE9178">'id', CE9178">'name', CE9178">'role'];
  
  return Object.fromEntries(
    keys.map(key => [key, raw[key] ?? CE9178">'default'])
  ) as User;
}

Why Object.fromEntries is a Game Changer

Object.fromEntries is the inverse of Object.entries. It takes an array of key-value pairs and turns them back into an object. When paired with TypeScript, it’s much cleaner than manually mutating an object.

The beauty of this approach is that it forces you to define the target schema explicitly. You can even combine this with Type-Safe Pipelines: Mastering Advanced TypeScript Transformations if you need to perform multiple transformation steps in a row.

Implementing a Type-Safe Normalizer

Let’s refine the approach to handle partial data, which is where most "undefined" errors originate.

TYPESCRIPT
type NormalizedData<T> = { [K in keyof T]-?: T[K] };

function safeNormalize<T extends object>(
  data: Partial<T>, 
  defaults: T
): T {
  return Object.fromEntries(
    Object.keys(defaults).map(key => [
      key, 
      data[key as keyof T] ?? defaults[key as keyof T]
    ])
  ) as T;
}

This safeNormalize function uses a mapped type to ensure that even if the input data is Partial<T>, the output is guaranteed to have all keys present (the -? modifier removes the optional status).

When Types Help (and When They Hurt)

I’ve found that over-engineering these normalizers can sometimes lead to "type-hell." If your data transformation logic becomes too complex, the TypeScript compiler might struggle to infer the types correctly, forcing you to use as assertions.

If you find yourself writing massive, recursive mapped types, stop and ask if a simple TypeScript type guard would be more readable. I often rely on TypeScript Type Guards: Stop Runtime Data Corruption in API Calls when the incoming data structure is truly unpredictable. It’s often better to validate the shape of the data at the edge of your app rather than trying to force it into a shape it doesn't fit.

Key Takeaways

  1. Don't mutate objects: Use Object.fromEntries to create new, validated objects from arrays.
  2. Use Mapped Types: Use -? to ensure your normalized objects don't have dangling optional properties.
  3. Default Values: Always provide a fallback for external data. If the API returns undefined, your app should treat it as a known default, not a crash-inducing surprise.

I’m still experimenting with how to best handle nested objects in these pipelines. Right now, I tend to use a flat normalization strategy because it's easier to debug, even if it means more boilerplate. Next time, I might try a recursive approach, but for now, keeping the data normalization logic shallow is saving me a ton of time during on-call rotations.

Back to Blog

Similar Posts

TypeScriptJavaScriptJune 23, 20264 min read

Preventing Runtime Property Errors with TypeScript Mapped Types

Preventing runtime property errors is easier with TypeScript. Learn to use keyof and mapped types for safe dynamic object access in your next refactor.

Read more
TypeScriptJavaScript
June 22, 2026
4 min read

TypeScript Feature Flags: Const Assertions & Mapped Types Guide

Master TypeScript feature flags using const assertions and mapped types. Learn to enforce compile-time safety and eliminate runtime configuration bugs.

Read more
Woman sitting on green rug working on laptop, surrounded by technology books in a modern room.
TypeScriptJavaScriptJune 21, 20264 min read

TypeScript Mapped Types for Effortless API Integration Syncing

TypeScript Mapped Types can automate your API integration, keeping frontend models in sync with backend contracts. Stop writing manual interfaces today.

Read more