DEV Community

Cover image for ๐Ÿงผ Type-Safe Filtering in TypeScript: Handling Nullable Fields from Your Database
Toshiya Matsumoto
Toshiya Matsumoto

Posted on • Edited 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)