TypeScript
tinyval is written in TypeScript. The data type is inferred from the schema, so you don't need to declare an interface separately.
Infer — type from a schema
ts
import { object, string, number, optional, array, oneOf, type Infer } from 'tinyval';
const User = object({
name: string(),
age: optional(number()),
role: oneOf(['admin', 'user']),
tags: array(string()),
});
type User = Infer<typeof User>;
// {
// name: string;
// role: 'admin' | 'user';
// tags: string[];
// age?: number | undefined;
// }Fields wrapped in optional without a default become optional (?). With transform the type is the result of the transformation.
Narrowing the result
validate returns a union: after checking valid, TypeScript knows whether data exists:
ts
const result = validate(User, input);
if (result.valid) {
result.data.name; // string
} else {
result.data; // undefined
result.errors; // Record<string, string>
}parse returns Infer<typeof User> directly.
Rule compatibility
A rule must match the schema type — the error is shown before you run the code:
ts
pipe(number(), minLength(2)); // error: minLength works with strings and arrays
pipe(string(), min(1)); // error: min works with numbersTypes in custom checks
The value type of check can be set explicitly:
ts
const even = check<number>((v) => v % 2 === 0, 'Must be even');Exported types
| Type | Description |
|---|---|
Schema<T> | A schema that returns a value of type T |
Infer<S> | The data type of schema S |
Result<T> | The result of validate |
Issue | An error: { code, message, path, params } |
Message | A string or a function (params) => string |
Options | Validation options: { all?, abortEarly?, messages?, labels?, maxDepth? } — see validate |
Action<T> | A rule or transform for pipe |
Info | The second argument of check: { parent, root } |