Skip to Content

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:

src/bookmark.ts
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?”

src/02-is.ts
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)); // false

Run it:

Terminal
npx ttsx src/02-is.ts

You’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:

src/02-assert.ts
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:

src/02-validate.ts
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

QuestionUse
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 Bookmark interface 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.

→ Step 3: Refining types

Last updated on