@miqro/parser
v2.0.6
Published
Schema validation and coercion with full TypeScript inference.
Downloads
609
Readme
@miqro/parser
Schema validation and coercion with full TypeScript inference.
basic usage
import { Parser } from "@miqro/parser";
const parser = new Parser();
// Type is inferred automatically from the schema
const result = parser.parse({ id: "1", title: "hello" }, {
type: "object",
properties: {
id: "integer",
title: "string",
published: "boolean?"
}
});
result.id // number (coerced from string)
result.title // string
result.published // boolean | undefinedIf you prefer to declare the schema separately, annotate it with Schema<T> to
carry the explicit type (inference still works on inline schemas without it):
import { Parser, Schema } from "@miqro/parser";
interface Post { id: number; title: string; published?: boolean; }
const PostSchema: Schema<Post> = {
type: "object",
properties: { id: "integer", title: "string", published: "boolean?" }
};
const post = parser.parse(raw, PostSchema); // → Posttype string syntax
"string" required string
"string?" optional string (undefined if absent)
"number" required number
"integer" required integer (coerced)
"boolean" required boolean ("true"/"false" coerced)
"string[]" array of strings
"string[]?" optional array of strings
"string[]!" force single value into array, always returns string[]
"string[]!?" optional force-array
"string|number" string or number (first match wins)
"string|number?" string or optional numberbuilt-in types
string, string1 (non-empty), number, integer, boolean
url, email, regex, regexp, function, any
object, array, dict, enum
decodeHTML, encodeHTML, schemaobject schema
const result = parser.parse(raw, {
type: "object",
properties: {
name: "string",
age: "integer?",
address: {
type: "object?",
properties: {
city: "string",
zip: "string?"
}
},
tags: {
type: "array",
arrayType: "string"
}
}
});
result.name // string
result.age // number | undefined
result.address?.city // string
result.tags // string[]mode
mode: "no_extra" (default) throws if unknown properties are present
mode: "remove_extra" strips unknown properties, returns defined shape only
mode: "add_extra" keeps unknown properties, type is defined shape & Record<string, unknown>const result = parser.parse(raw, {
type: "object",
mode: "add_extra",
properties: { id: "integer" }
});
result.id // number
result["anything"] // unknownarray
// array of primitives
parser.parse(raw, { type: "array", arrayType: "string" }); // string[]
// array of objects — define element shape with co-located properties
const result = parser.parse(raw, {
type: "array",
arrayType: "object",
properties: {
id: "integer",
label: "string"
}
});
result[0].id // number
result[0].label // string
// array of arrays
parser.parse(raw, { type: "array", arrayType: "number[]" }); // number[][]enum
const result = parser.parse(raw, {
type: "enum",
enumValues: ["a", "b", "c"]
});
// result → "a" | "b" | "c"dict
// dict of primitives
parser.parse(raw, { type: "dict", dictType: "number" });
// → Record<string, number>
// dict of objects — define value shape with co-located properties
const result = parser.parse(raw, {
type: "dict",
dictType: "object",
properties: { x: "string", y: "number?" }
});
result["key"].x // string
result["key"].y // number | undefinedAliases: Dict<string>, dict<string> are equivalent as type strings.
allowNull
parser.parse(raw, { type: "string", allowNull: true }); // string | null
parser.parse(raw, { type: "enum", enumValues: ["a", "b"], allowNull: true }); // "a" | "b" | nullInferSchema utility type
Use InferSchema<S> to derive the TypeScript type from a schema definition
without calling parse:
import { InferSchema } from "@miqro/parser";
type T1 = InferSchema<"string?">; // string | undefined
type T2 = InferSchema<"number[]">; // number[]
type T3 = InferSchema<{ type: "object"; properties: { x: "string" } }>; // { x: string }
type T4 = InferSchema<{ type: "enum"; enumValues: readonly ["a","b"] }>; // "a" | "b"
type T5 = InferSchema<{ type: "number"; allowNull: true }>; // number | nullcustom parser
import { Parser } from "@miqro/parser";
const parser = new Parser();
parser.register("uuid", (value) => {
if (typeof value === "string" && /^[0-9a-f-]{36}$/.test(value)) {
return value;
}
// return undefined or throw ParseOptionsError to fail validation
});
parser.parse("123e4567-...", "uuid"); // → unknownTo get type inference for custom parsers, augment TypeMap in the module
where it is declared:
declare module "@miqro/parser/build/built-in-parsers" {
interface TypeMap {
uuid: string;
}
}
parser.parse("123e4567-...", "uuid"); // → string
parser.parse(raw, "uuid[]"); // → string[]
parser.parse(raw, "dict<uuid>"); // → Record<string, string>