---
title: "One Model, Many Views: Type-Safe Transforms with Valibot and doba"
url: https://daily.dev/posts/one-model-many-views-type-safe-transforms-with-valibot-and-doba-jdqcdjqot
source_url: https://valibot.dev/blog/same-data-different-shapes
type: article
source: "Valibot: The modular and type safe schema library"
published: 2026-08-23T12:23:35.370Z
updated: 2026-08-23T12:55:18.364Z
tags: ["typescript"]
reading_time: 6
upvotes: 0
comments: 0
language: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# One Model, Many Views: Type-Safe Transforms with Valibot and doba

**[Valibot: The modular and type safe schema library](https://daily.dev/sources/valibot)** · 6 min read · 0 upvotes · 0 comments

## Summary

A guest post introduces doba, a schema registry library that pairs with Valibot (or any Standard Schema compatible library) to manage type-safe transformations between different data shapes, such as database rows, frontend views, AI-model inputs, and legacy API formats. Instead of writing ad hoc mapping functions, developers register schemas and define migrations between them; doba automatically chains migrations to find paths between schemas that have no direct transform defined. It also supports a migration context for recording defaulted or guessed values during conversions, a pipe builder for mechanical renames/drops with type-checked chaining, and schema identification for unknown incoming data via field matchers. Use cases highlighted include API versioning, LLM prompt formatting, legacy data imports, and webhook payload normalization.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://valibot.dev/blog/same-data-different-shapes>

## Questions this post answers

### How can I automatically chain data transformations between schemas that don't have a direct migration defined in TypeScript?

A schema registry can walk a graph of defined migrations and chain intermediate ones automatically. For example, if only database-to-frontend and frontend-to-ai migrations are registered, calling a transform from database to ai still works because the registry routes through the frontend schema, without requiring a direct database-to-ai migration to be written.

_Developers comparing data-mapping approaches can find write-ups like this on daily.dev._

### How do I track why fields were defaulted during a legacy data migration in TypeScript?

Pass a context object into each migration function that exposes methods like ctx.defaulted() and ctx.warn() to record decisions made during conversion, such as generating a missing id or guessing an email from a name field. These records appear in the transform result's meta.defaults and meta.warnings arrays so the reasoning is preserved instead of disappearing into function bodies.

_Teams handling messy legacy imports often track patterns like this via daily.dev._

### How can I detect which schema an unknown piece of data matches before transforming it in a TypeScript app?

Define identify guards per schema using field matchers such as match.field('passwordHash') or match.fields('createdAt', 'settings'), then call identifyAndTransform on the unknown data and a target schema name. Guards run in definition order, detecting the source schema, chaining the migration path, and returning a typed error rather than crashing if nothing matches.

_daily.dev surfaces practical patterns like this for developers normalizing inconsistent payloads._

---

Tags: [#typescript](https://daily.dev/tags/typescript)

[View this post on daily.dev](https://daily.dev/posts/one-model-many-views-type-safe-transforms-with-valibot-and-doba-jdqcdjqot)
