zmdbzero-maintenance data layer
Docs Benchmarks Anti-patterns OpenAPI
Docs / Schema and ORM

Type DerivationSupported

No hand-written DTOs. Every DTO derives from the interface you declared the table as:

import { type Entity, type CreateDTO, type UpdateDTO } from '@zmdb/schema';

// interface User extends Table<'users'> { … } — see Schema Declaration.

type UserRow = Entity<User>;
// { id: number; email: string; role: 'admin'|'user'|'guest'; createdAt: Date }

type CreateUser = CreateDTO<User>;
// { email: string; role?: 'admin'|'user'|'guest' }
//   id omitted (Serial); role/createdAt optional (HasDefault)

type UpdateUser = UpdateDTO<User>;
// every column optional, minus the serial ones and the primary key

The argument is the type, not the schema value. Entity<User>, never Entity<typeof UserSchema> — a schema value is data for the query compiler and the migration emitter, and it has nowhere to put a json column's payload shape, so nothing derives a row type from one. Where you hold a value and need its type, hand it to something that asks for one: defineRepository(schemaOf<User>(), driver) gives you a repository whose every method is already typed in User, with no annotation.

These are the same types the validators and serializers are generated against, so the request DTO, the DB write, and the response type can never drift apart.

❗ Important

This is the anti-drift guarantee: change a column and all three types update. Any code that no longer satisfies them fails to compile — there is no runtime schema object to fall out of sync with.

Beyond the write triad, the read side also derives typed DTOs — GetDTO, ListDTO/ListResult, SearchDTO, Projection, Populated and AggregateResult. See Read/Query DTOs.