DEV Community

Cover image for 🧼 Type-Safe Filtering in TypeScript: Handling Nullable Fields from Your Database
Toshiya Matsumoto
Toshiya Matsumoto

Posted on

🧼 Type-Safe Filtering in TypeScript: Handling Nullable Fields from Your Database

🌟 The Challenge: Bridging Type Safety Between DB and App Layers

In many real-world applications, the database schema often permits null values — for good reason. For instance, a date field in an event table might be intentionally left blank if the event date hasn’t been finalized yet.

However, your application layer — especially the part that renders UI — usually prefers clean, reliable data. If a date is null, you probably don’t want to show that event in the UI at all.

This creates a gap between what your database allows and what your application expects.

You might be tempted to solve this quickly with a forced type cast like:

let x: unknown = 'hello';
console.log((x as string).length);
But relying on type assertions skips safety checks and can lead to runtime bugs — exactly what TypeScript is meant to help you avoid.
Enter fullscreen mode Exit fullscreen mode

🎯 The Solution: Using Type Guards

Instead of casting, a safer and cleaner solution is to use Type Guards — a TypeScript feature that allows you to narrow types in a type-safe way.

Let’s say your application pulls in event data like this:

// event.dto.ts - from database or external API
type EventDto = {
  name: string;
  date: Date | null;
};
Enter fullscreen mode Exit fullscreen mode

But your UI layer expects all events to have a valid date:

// event.ts - for use within the app
type Event = {
  name: string;
  date: Date;
};
Enter fullscreen mode Exit fullscreen mode

To filter out incomplete events, define a custom type guard:

function hasDate(event: EventDto): event is Event {
  return event.date !== null;
}
Enter fullscreen mode Exit fullscreen mode

Then you can filter safely and TypeScript will infer the correct type:

export function filterValidEvents(events: EventDto[]): Event[] {
  return events.filter(hasDate);
}
Enter fullscreen mode Exit fullscreen mode

Now your UI layer will only receive events that have confirmed dates — and TypeScript will enforce this guarantee for you.

✅ Benefits

Type safety without unnecessary assertions.

Separation of concerns: the DB layer can remain flexible, while the app layer stays strict.

Scalability: you can extend this pattern to other nullable fields and DTOs.

🧠 Final Thoughts

Dealing with partial or nullable data from external sources is inevitable. But with TypeScript’s type guards, you don’t have to compromise safety or clarity.
Embrace the gap between layers — and bridge it elegantly.

Top comments (0)