Skip to Content

Step 3 — Refining types with tags

The Bookmark interface from the last step accepts any string for url and any string array for tags. That’s not realistic — we want url to actually be a URL, and we’d like tags to be a non-empty array of short strings.

typia adds these constraints through type tags that you intersect into the base type. They are real TypeScript types, so the compiler enforces correctness (no typos in tag names), and the runtime validator picks them up automatically.

Tightening Bookmark

Replace your bookmark.ts with this version:

src/bookmark.ts
import { tags } from "typia"; export interface Bookmark { /** * Stable identifier. UUID v4. */ id: string & tags.Format<"uuid">; /** * The URL we're saving. */ url: string & tags.Format<"url"> & tags.MaxLength<2048>; /** * Human-readable title for the link. */ title: string & tags.MinLength<1> & tags.MaxLength<200>; /** * Optional one-paragraph description. */ description?: string & tags.MaxLength<5000>; /** * Tags for filtering / grouping. * At least one tag, no more than 16, each ≤ 32 characters. */ tags: Array<string & tags.MaxLength<32>> & tags.MinItems<1> & tags.MaxItems<16>; /** * When the bookmark was created. */ createdAt: string & tags.Format<"date-time">; }

What changed:

  • id must be a UUID
  • url must be a URL of at most 2 048 characters
  • title must be between 1 and 200 characters
  • description is still optional but capped at 5 000 characters
  • tags is a 1–16 element array; each element is at most 32 characters
  • createdAt must be an ISO-8601 date-time

Everything else stays the same. The validators we wrote in step 2 immediately pick up the new constraints — no changes to their call sites.

See the new errors

src/03-tags.ts
import typia from "typia"; import { Bookmark } from "./bookmark"; const candidate: unknown = { id: "not-a-uuid", url: "lol", title: "", tags: [], createdAt: "yesterday", }; const result = typia.validate<Bookmark>(candidate); if (!result.success) { for (const err of result.errors) { console.log(`${err.path}: expected ${err.expected}, got`, err.value); } }

Run it:

Terminal
npx ttsx src/03-tags.ts
$input.id: expected string & Format<"uuid">, got 'not-a-uuid' $input.url: expected string & Format<"url">, got 'lol' $input.title: expected string & MinLength<1>, got '' $input.tags: expected Array<…> & MinItems<1>, got [] $input.createdAt: expected string & Format<"date-time">, got 'yesterday'

The expected strings echo back the same intersection syntax you wrote in bookmark.ts. If you ever wonder “what was supposed to be there?”, the error literally tells you.

The tag catalogue (the parts we’ll use)

TagBase typeWhat it does
tags.Format<"uuid" | "email" | "url" | "date" | "date-time" | …>stringBuilt-in format check
tags.MinLength<N> / tags.MaxLength<N>stringLength bounds
tags.Pattern<"...">stringRegex
tags.Minimum<N> / tags.Maximum<N>number, bigintRange
tags.Type<"int32" | "uint32" | "float" | ...>number, bigintSub-type
tags.MinItems<N> / tags.MaxItems<N>Array<T>Length bounds
tags.UniqueItemsArray<T>Pairwise distinct

The full list is on the Special Tags page. Tags compose with & and | like any other TypeScript type — you can build expressions like (number & tags.Type<"int32">) | (bigint & tags.Type<"uint64">).

Bonus — making test data that satisfies the type

Now that the type is precise, typia.random can produce realistic instances:

src/03-random.ts
import typia from "typia"; import { Bookmark } from "./bookmark"; const fake = typia.random<Bookmark>(); console.log(fake);
{ id: '8d62f9c0-...', url: 'http://example.com/...', title: 'p0WkQNbe...', tags: [ 'L8b', 'kHrJ' ], createdAt: '2049-...' }

You get a value that satisfies every constraint on the type. Useful for test fixtures and for seeding development databases.

What you’ve done

  • Replaced loose primitive types with tagged variants that carry constraints
  • Watched the validator’s error messages tighten automatically
  • Generated realistic fake bookmarks straight from the type

Next we’ll save and load these bookmarks to disk — and use typia to make sure the file we read back actually contains what we expect.

→ Step 4: JSON parse & stringify

Last updated on