|
| 1 | +# Schema Type System |
| 2 | + |
| 3 | +This module provides a flexible, TypeScript-friendly schema/type system for runtime validation, parsing, and type inference. It is inspired by libraries like [valita](https://github.com/badrap/valita). |
| 4 | + |
| 5 | +## Features |
| 6 | +- Define schemas for primitives, objects, arrays, tuples, unions, literals, and functions |
| 7 | +- Parse and validate data at runtime |
| 8 | +- Type inference for static TypeScript types |
| 9 | +- Extensible and composable |
| 10 | + |
| 11 | +## Installation |
| 12 | + |
| 13 | +This module is part of the `github-zeed` project. To use it, import from the appropriate path: |
| 14 | + |
| 15 | +```ts |
| 16 | +import { array, Infer, literal, number, object, string, union, z } from './schema' |
| 17 | +// z.string and string are functionally alike, but z.string is preferred for consistency. |
| 18 | +``` |
| 19 | + |
| 20 | +## Basic Usage |
| 21 | + |
| 22 | +### Primitives |
| 23 | + |
| 24 | +```ts |
| 25 | +const name = z.string() |
| 26 | +const age = z.number() |
| 27 | +// Type: string, number |
| 28 | +``` |
| 29 | + |
| 30 | +### Objects |
| 31 | + |
| 32 | +```ts |
| 33 | +const user = z.object({ |
| 34 | + name: z.string(), |
| 35 | + age: z.number().optional(), |
| 36 | +}) |
| 37 | +// Type: { name: string; age?: number } |
| 38 | +``` |
| 39 | + |
| 40 | +### Arrays |
| 41 | + |
| 42 | +```ts |
| 43 | +const tags = z.array(z.string()) |
| 44 | +// Type: string[] |
| 45 | +``` |
| 46 | + |
| 47 | +### Unions |
| 48 | + |
| 49 | +```ts |
| 50 | +const status = z.union([ |
| 51 | + z.literal('active'), |
| 52 | + z.literal('inactive'), |
| 53 | +]) |
| 54 | +// Type: 'active' | 'inactive' |
| 55 | +``` |
| 56 | + |
| 57 | +### Type Inference |
| 58 | + |
| 59 | +```ts |
| 60 | +type User = Infer<typeof user> |
| 61 | +// Equivalent to: { name: string; age?: number } |
| 62 | +``` |
| 63 | +
|
| 64 | +### Parsing |
| 65 | +
|
| 66 | +```ts |
| 67 | +const parsed = user.parse({ name: 'Alice', age: 30 }) |
| 68 | +// parsed: { name: 'Alice', age: 30 } |
| 69 | +``` |
| 70 | + |
| 71 | +### Optional and Default Values |
| 72 | + |
| 73 | +```ts |
| 74 | +const score = z.number().optional().default(0) |
| 75 | +// Type: number | undefined (default: 0) |
| 76 | +``` |
| 77 | + |
| 78 | +### Function and RPC Types |
| 79 | + |
| 80 | +```ts |
| 81 | +const add = z.func([z.number(), z.number()], z.number()) |
| 82 | +// Type: (a: number, b: number) => number |
| 83 | +const rpcCall = z.rpc(z.object({ id: z.string() }), z.number()) |
| 84 | +// Type: (info: { id: string }) => number | Promise<number> |
| 85 | +``` |
| 86 | + |
| 87 | +## API Reference |
| 88 | + |
| 89 | +- `string()`, `number()`, `int()`, `boolean()`, `none()`, `any()` |
| 90 | +- `object({...})`, `array(type)`, `tuple([type1, type2, ...])`, `record(type)` |
| 91 | +- `union([type1, type2, ...])` |
| 92 | +- `literal(value)`, `stringLiterals(['a', 'b', ...])` |
| 93 | +- `func(args, ret)`, `rpc(info, ret)` |
| 94 | +- `.optional()`, `.default(value)`, `.props({ desc })`, `.extend({...})` |
| 95 | +- `parse(obj)`, `map(obj, fn)` |
| 96 | + |
| 97 | +## Notes |
| 98 | + |
| 99 | +- `z.string` and `string` are functionally equivalent, but `z.string` is preferred for consistency and clarity. |
| 100 | +- Each schema definition results in a corresponding TypeScript type, which can be extracted using `Infer<typeof schema>`. |
0 commit comments