Skip to content

Type Inference

Anhanga provides full TypeScript inference. InferRecord extracts a typed record directly from your schema definition.

InferRecord

typescript
import type { InferRecord } from '@anhanga/core'

type PersonRecord = InferRecord<typeof PersonSchema>
// {
//   id: string
//   name: string
//   email: string
//   phone: string
//   birthDate: string
//   active: boolean
//   street: string
//   city: string
// }

The inferred types match each field factory's data type:

FactoryInferred Type
text()string
number()number
currency()number
date()string
datetime()string
toggle()boolean
checkbox()boolean
select<V>()V
file()File
image()File

Type-Safe Events and Handlers

SchemaDefinition.events() and SchemaDefinition.handlers() validate field names and handler names against the schema:

typescript
// TypeScript will catch typos
const events = PersonSchema.events({
  naem: { /* ... */ },  // ❌ Error: 'naem' is not a field in PersonSchema
})

Using with Services

The inferred type works with ServiceContract:

typescript
type PersonRecord = InferRecord<typeof PersonSchema>

const personService: ServiceContract<PersonRecord> = {
  async create(data: Partial<PersonRecord>) { /* ... */ },
  async read(id: string) { /* ... */ },
  async update(id: string, data: Partial<PersonRecord>) { /* ... */ },
  async destroy(id: string) { /* ... */ },
  async paginate(params) { /* ... */ },
}

extend, pick, omit

Type inference is preserved through schema transformations:

typescript
const EmployeeSchema = PersonSchema.extend('employee', {
  fields: { department: text(), salary: currency() },
})

type EmployeeRecord = InferRecord<typeof EmployeeSchema>
// PersonRecord & { department: string; salary: number }

type NameOnly = InferRecord<ReturnType<typeof PersonSchema.pick<'name' | 'email'>>>
// { name: string; email: string }

Released under the MIT License.