import { type } from "arktype"const user = type({ name: "string", platform: "'android' | 'ios'", "versions?": "(number | string)[]"})// extract the type if neededtype User = typeof user.infer
If you make a mistake, don't worry- every definition gets the autocomplete and validation you're used to from your editor, all within TypeScript's type system.
:::note[Will ArkType crash my TypeScript server?]
Thousands of hours of optimization have gone into making validating native type syntax not just feasible, but often much faster than alternatives ⚡
:::
At runtime, we can pass unknown data to our type and get back either a validated User or an array of clear, customizable errors with a root summary.
const user = type({ name: "string", device: { platform: "'android' | 'ios'", "versions?": "(number | string)[]" }})interface RuntimeErrors extends type.errors { /**device.platform must be "android" or "ios" (was "enigma")device.versions[2] must be a number or a string (was bigint)*/ summary: string}const narrowMessage = (e: type.errors): e is RuntimeErrors => true// ---cut---const out = user({ name: "Alan Turing", device: { platform: "enigma", versions: [0, "1", 0n] }})if (out instanceof type.errors) { // ---cut-start--- // just a trick to display the runtime error if (!narrowMessage(out)) throw new Error() // ---cut-end--- // hover out.summary to see validation errors console.error(out.summary)} else { // hover out to see your validated data console.log(`Hello, ${out.name}`)}
And that's it! You now know how to to define a Type use it to check your data at runtime.
Next, we'll take a look at how ArkType extends TypeScript's type system to handle runtime constraints like maxLength and pattern.