Type Guard Generator
Paste a TypeScript interface or type and get a real, recursive runtime type guard — not a shallow shape check. It parses primitives, literals, arrays, unions, nested inline objects and references to your other declarations, then emits isUser(value): value is User with proper Array.isArray + element checks, optional handling and nested object descent. Optionally add a throwing assertUser(), and use the live validator to run the parsed type against any JSON value and see the exact failing paths.
About this ToolHow it works, benefits & use casesTap to collapse
Paste a TypeScript interface or type and get a real, recursive runtime type guard rather than a shallow shape check. A tolerant parser reads your declarations - primitives, string/number/boolean literals, arrays (T[] and Array<T>), unions, nested inline object literals, and references to your other interfaces in the same input - into an internal schema, then emits a complete user-defined type guard of the form export function isUser(value: unknown): value is User. Object properties get the right typeof checks, arrays use Array.isArray plus a per-element check, optional properties allow undefined, unions become OR-ed checks, and a reference like orders: Order[] is wired up to call the generated isOrder guard. You can additionally emit a throwing assertUser(value): asserts value is User, choose deep recursive checks versus a shallow shape-only guard, and emit a shared isRecord helper. A built-in validator runs the parsed schema (not the generated code - nothing is eval-ed) against any JSON value you paste and lists the exact failing field paths. Everything runs in your browser and the whole setup lives in a shareable URL.
How to Use
- 1Paste one or more TypeScript interface or type declarations into the editor (or load an example).
- 2When there are several declarations, pick which one the Test panel validates against with the Validator root selector.
- 3Toggle Deep checks to recurse into arrays and nested objects, or turn it off for a fast shallow shape check.
- 4Enable Assertion function to also emit a throwing assertX, and isRecord helper for the shared object check.
- 5Read the generated guards in the sticky output panel, then copy, download, or share the result.
- 6Paste a sample JSON value into Test a value to see whether it passes and which field paths fail.
Key Benefits
- Parses interfaces, type aliases, literals, arrays, unions, nested inline objects and cross-references
- Emits a true value is Type guard that narrows the type in any true branch
- Recurses into nested objects and validates array elements with Array.isArray + a per-element check
- Wires references between your declarations into nested is<Other> guard calls in dependency order
- Optional throwing assertX functions and a shared isRecord helper
- A live validator runs the parsed schema against any JSON and reports exact failing paths
- Pure, in-browser generation with a shareable URL - no code is eval-ed
Common Use Cases
- Validating untyped API or fetch responses before trusting them as a typed object
- Guarding parsed JSON or localStorage data at runtime boundaries
- Narrowing unknown values in error handlers or postMessage handlers
- Generating composable guards for related DTOs that reference one another
- Confirming a draft type accepts the payloads you expect and rejects the ones you do not
Generated runtime type guards
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
export function isUser(value: unknown): value is User {
return (
isRecord(value) &&
typeof value.id === 'number' &&
typeof value.name === 'string' &&
typeof value.email === 'string' &&
(value.age === undefined || typeof value.age === 'number') &&
(value.role === 'admin' || value.role === 'user' || value.role === 'guest') &&
Array.isArray(value.tags) && value.tags.every((el: unknown) => typeof el === 'string')
);
}
Test a value
Paste a JSON value to run against isUser.
TypeScript interface / type
Tip: paste several declarations — references between them (e.g. orders: Order[]) are wired up into nested isOrder(...) calls.
Output options
recurse into arrays + nested objects
also emit assertX (throws)
shared object-shape helper
A guard that actually narrows
The output is a user-defined type guard: value is Type. Inside any branch where it returns true, TypeScript narrows the value to your type. Arrays use Array.isArray plus a per-element check, optional properties allow undefined, and unions become OR-ed checks.
Unsupported constructs
The parser handles the common 90%. Generics, mapped/conditional types, intersections (A & B), index signatures and extends clauses are skipped or treated as unknown rather than failing — refine those checks by hand.
Was this tool helpful?
Share Your Experience
Help others discover this tool!
Related tools
- JSON to TypeScriptGenerate TypeScript interfaces from JSON
- TypeScript FormatterFormat and beautify TypeScript code
- Changelog GeneratorGenerate changelog from Git commit history
- Component Name GeneratorTurn a description into ranked, kind-aware component names with a file scaffold and a name validator (casing, collisions, clarity)
- Heroku Procfile GeneratorBuild a Heroku Procfile and matching app.json — process types, env vars, addons, dyno formation — plus a Procfile parser and audit
- Markdown TOC GeneratorGenerate table of contents for Markdown
It builds an internal schema from your type and emits recursive checks rather than a single non-null object test. Arrays validate every element, nested inline objects are descended into, string/number/boolean literals are compared by value, unions become OR-ed checks, and a reference to another interface in the same input is wired up as a call to that type guard - emitted in dependency order so referenced guards are defined first.
Alongside each isX guard it emits assertX(value): asserts value is X, which calls the guard and throws a TypeError when the value does not match. Assertion functions are handy at trust boundaries where you would rather fail loudly than branch - after the call, TypeScript treats the value as the asserted type for the rest of the scope.

