TypeScript-shaped runtime validation

Types that make it to runtime.

Use a plain object as the schema. Validate unknown data and get the inferred TypeScript type—without a builder DSL.

Read the docs →
litetype.ts
import {
  string, number, parse, type Infer,
} from 'litetype'

// One object is the runtime schema
const User = {
  name: string.min(1),
  age: number.min(0),
  'email?': string.email(),
}

// Same object gives the TypeScript type
type User = Infer<typeof User>

// unknown in, typed User out
const user = parse(User, input)

The model

Three things, separate

valueconst User = { name: string }
typetype User = Infer<typeof User>
checkparse(User, input)

Measured, not claimed

Performance and size

5.00 kB
browser bundle, min + gzip
90.47M
flat valid objects / second
341
TypeScript instantiations
0
runtime dependencies
See contracts and methodology →

Schemas are data

Composition

Spread is extend. Property access is pick. Rest destructuring is omit. Optional keys remain optional because the language already knows how objects compose.

TypeScript
import { date, number, string } from 'litetype'

const User = { name: string, age: number, 'email?': string }
const Timestamps = { createdAt: date, 'deletedAt?': date }

const Post = { title: string, ...Timestamps }
const Public = { name: User.name, 'email?': User['email?'] }
const { age: _, ...NoAge } = User

Less library language

Compared with Zod

Zod
import { z } from 'zod'

const User = z.object({
  name: z.string().min(1),
  email: z.string().email().optional(),
})

type User = z.infer<typeof User>
User.parse(input)
litetype
import { type Infer, parse, string } from 'litetype'

const User = {
  name: string.min(1),
  'email?': string.email(),
}

type User = Infer<typeof User>
parse(User, input)
Move from Zod →

One standard edge

Ecosystem

Keep schemas bare inside your code. Wrap once with Standard Schema where another tool needs it.

TypeScript
import { standard, string } from 'litetype'

const User = { name: string.min(1) }

t.procedure
  .input(standard(User))
  .query(({ input }) => input)
Integration recipes →

Install