Step 2 — Your first validator
We’ll define the Bookmark interface — the data model we’ll use through the rest of the tutorial — and write three different validators against it: is, assert, and validate. They look almost identical to call, but each one is the right pick for a different situation. We’ll see all three.
The Bookmark interface
Make a new file:
export interface Bookmark {
/** Stable identifier. */
id: string;
/** The URL we're saving. */
url: string;
/** Human-readable title for the link. */
title: string;
/** Optional one-paragraph description. */
description?: string;
/** Tags for filtering / grouping. */
tags: string[];
/** When the bookmark was created (ISO-8601 string). */
createdAt: string;
}That’s just TypeScript — no decorators, no schema builder. typia will read this interface directly.
typia.is — “does this look like a Bookmark?”
import typia from "typia";
import { Bookmark } from "./bookmark";
const good: unknown = {
id: "b1",
url: "https://typia.io",
title: "typia",
tags: ["docs", "validation"],
createdAt: "2026-05-16T09:00:00.000Z",
};
const bad: unknown = {
id: "b2",
// url missing
title: "broken",
tags: ["broken"],
createdAt: "2026-05-16T09:00:00.000Z",
};
console.log(typia.is<Bookmark>(good)); // true
console.log(typia.is<Bookmark>(bad)); // falseRun it:
npx ttsx src/02-is.tsYou’ll see true then false. The compiled JavaScript expanded typia.is<Bookmark> into a hand-rolled checker for the shape of Bookmark — no schema lookup at runtime. Curious what it looks like? Run npx ttsc and read dist/02-is.js.
is is a type guard: TypeScript narrows the variable on the true branch. So this is also legal:
function describe(input: unknown) {
if (typia.is<Bookmark>(input)) {
// input is now typed as Bookmark
console.log(`${input.title} → ${input.url}`);
}
}typia.assert — throw the first error
is only tells you yes or no. When you actually want the program to stop on a bad input — for example, when an HTTP request body arrives and you need to refuse to handle it — use assert:
import typia from "typia";
import { Bookmark } from "./bookmark";
const bad: unknown = {
id: "b3",
url: 42, // wrong type
title: "broken",
tags: ["broken"],
createdAt: "2026-05-16T09:00:00.000Z",
};
try {
typia.assert<Bookmark>(bad);
} catch (err) {
console.log(err);
}Run it. You’ll see a TypeGuardError with structured fields:
TypeGuardError {
method: 'typia.assert',
path: '$input.url',
expected: 'string',
value: 42,
...
}That path is the killer feature. You can drop it into a UI message (“the field url should be a string”), pipe it to logs, or attach it to an HTTP 400 response. No string parsing required.
assert returns the input on success, so you can wrap it inline:
const safe: Bookmark = typia.assert<Bookmark>(rawInput);
// the next line is statically typed as Bookmark
console.log(safe.title);typia.validate — collect every error
For forms or any UI that wants to highlight every bad field at once, assert stops too early — it throws on the first one. Use validate instead:
import typia from "typia";
import { Bookmark } from "./bookmark";
const messy: unknown = {
id: 42, // wrong: should be string
url: 9999, // wrong: should be string
title: "broken",
tags: "not an array", // wrong: should be string[]
createdAt: "2026-05-16T09:00:00.000Z",
};
const result = typia.validate<Bookmark>(messy);
if (result.success) {
console.log("OK:", result.data);
} else {
for (const err of result.errors) {
console.log(`${err.path}: expected ${err.expected}, got`, err.value);
}
}Run it and you’ll get all three errors in one pass:
$input.id: expected string, got 42
$input.url: expected string, got 9999
$input.tags: expected Array<string>, got 'not an array'result.success is the discriminator. On the true branch result.data is typed as Bookmark. On the false branch result.errors is an array of { path, expected, value } records.
How to choose
| Question | Use |
|---|---|
| Just a yes/no answer? | is |
| Want an exception to propagate? | assert |
| Need to render every error at once? | validate |
| Want to also reject extra properties? | append Equals: assertEquals, validateEquals, equals |
What you’ve done
- Defined the
Bookmarkinterface as plain TypeScript - Validated three different ways, with the validator generated from the interface itself
- Seen the structured error path that typia produces for free
Next we’ll tighten the type so the validator catches more than just “is this a string?” — it’ll also check URL format, minimum length, max length, and so on.