typia.is() โ quick yes / no type check
function is<T>(input: T): input is T;
function is<T>(input: unknown): input is T;typia.is<T> is the simplest validator: it returns true if input matches type T, and false otherwise.
It is also a type guardย , so on the true branch TypeScript narrows the variable to T automatically โ you donโt have to cast.
| Scenario | Pick |
|---|---|
| Just a yes/no answer | is (you are here) |
| One field is wrong โ throw an exception | assert |
| Need every field error at once (form, LLM feedback loop) | validate |
First example
import typia from "typia";
interface User {
id: string;
age: number;
}
const input: unknown = await fetchSomething();
if (typia.is<User>(input)) {
// input is now `User` inside this block
console.log(input.age);
}Thatโs the whole API. Behind the scenes, typia rewrites typia.is<User> at compile time into a hand-written checker specialized to User โ no schema lookup, no reflection. The result is the fastest validator in the JavaScript ecosystem; see pure TypeScript for the long explanation.
The tabs below show the same example as a full source file (left) and the JavaScript typia actually emits (right). The โCompiled JavaScriptโ side is what your bundler ships โ thereโs no schema interpreter at runtime, just the inline checks. (Youโll see this same source/compiled-output tab pattern on every validator page.)
TypeScript Source
import typia, { tags } from "typia";
import { v4 } from "uuid";
const matched: boolean = typia.is<IMember>({
id: v4(),
email: "samchon.github@gmai19l.com",
age: 30,
});
console.log(matched); // true
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}Boolean only
You get a boolean. No path, no expected type, no list of errors. If you need any of that, jump to:
assertโ throw aTypeGuardErrorcarrying the first failing pathvalidateโ return anIValidationwith every failing path
If a yes/no answer is all you need, is is the right pick because the emitted code is the shortest.
Strict (equals)
interface Point { x: number; y: number; }
typia.is<Point>({ x: 1, y: 2, z: 3 }); // โ true (z is ignored)
typia.equals<Point>({ x: 1, y: 2, z: 3 }); // โ false (z is rejected)typia.equals<T> has exactly the same signature as typia.is<T> but also rejects any property that isnโt declared on T. Use it when extra fields should be a hard error โ for example, when validating data that someone else might have over-populated.
TypeScript Source
import typia, { tags } from "typia";
import { v4 } from "uuid";
const input: unknown = {
id: v4(),
email: "samchon.github@gmail.com",
age: 30,
extra: "superfluous property", // extra
};
const is: boolean = typia.is<IMember>(input);
const equals: boolean = typia.equals<IMember>(input);
console.log(is, equals); // true, false
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}Reusable checkers
Every typia.is<T> call expands into the type-specific checker at that call site. If you call it from 20 places with the same T, you get 20 copies in the compiled JavaScript. To avoid that, hoist the checker with typia.createIs<T>():
import typia from "typia";
const isUser = typia.createIs<User>();
// ...elsewhere
if (isUser(input)) { /* ... */ }typia.createEquals<T>() is the strict counterpart. Both factories take no arguments and return a plain (input: unknown) => input is T function.
TypeScript Source
import typia, { tags } from "typia";
export const check = typia.createIs<IMember>();
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}Type narrowing
Because typia.is<T> is declared as a TypeScript type predicate (input is T), the compiler narrows the variable for you:
import typia, { tags } from "typia";
import { v4 } from "uuid";
const input: unknown = {
id: v4(),
email: "samchon.github@gmail.com",
age: 30,
};
if (typia.is<IMember>(input)) {
// auto type casting
console.log(input.id, input.email, input.age);
}
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}You will see this pattern a lot in HTTP handlers, message bus consumers, and anywhere a value enters the program with type unknown.
What it doesnโt check
typia.is<T> walks structural properties; it does not call instanceof for user-defined classes, and it does not dive into function types.
-
User-defined classes โ
typia.is<MyClass>(input)only checksinputโs properties againstMyClass. If you also needinput instanceof MyClass, write that check yourself. -
Function types โ function-typed properties are skipped by default. To make
is/assert/validateconfirm those properties are actually callable, enable thefunctionaltransform flag intsconfig.json:tsconfig.json{ "compilerOptions": { "plugins": [ { "transform": "typia/lib/transform", "functional": true } ] } }
Built-in classes โ Date, Uint8Array, Set<T>, Map<K, V> โ are checked properly, including their elements:
TypeScript Source
import typia from "typia";
typia.createIs<Map<string, boolean | number | string>>();So the rule is โskip user-defined classes and functions; check everything elseโ, and the only thing you commonly need to add yourself is instanceof MyClass on top.
Constraints
number is a useful type. number & tags.Type<"uint32"> & tags.Minimum<1> is much more useful. typia lets you intersect type tags into a base type to express constraints like โnon-negative integerโ, โvalid emailโ, โ1-100 stringโ. They participate in is, assert, validate, random โ every validator-shaped function.
TypeScript Source
import typia, { tags } from "typia";
export const checkSomething = typia.createIs<Something>();
//----
// DEFINE CUSTOM TYPE TAGS
//----
type Dollar = tags.TagBase<{
kind: "dollar";
target: "string";
value: undefined;
validate: `$input[0] === "$" && !isNaN(Number($input.substring(1).split(",").join("")))`;
}>;
type Postfix<Value extends string> = tags.TagBase<{
kind: "postfix";
target: "string";
value: Value;
validate: `$input.endsWith("${Value}")`;
}>;
type IsEven<Value extends number | bigint> = tags.TagBase<{
kind: "isEven";
target: Value extends number ? "number" : "bigint";
value: undefined;
validate: `$input % ${Numeric<2>} === ${Numeric<0>}`;
}>;
type Numeric<Value extends number | bigint> = Value extends number
? Value
: `BigInt(${Value})`;
//----
// VALIDATION
//----
interface Something {
dollar: string & Dollar;
postfix: string & Postfix<"!!!">;
isEven: number & IsEven<number>;
}See Special Tags for the full catalogue.
Performance
typia.is<T> is the fastest of the validators โ it ships only the comparison logic, no error-collection, no path tracking. It is also the fastest validator across the JavaScript ecosystem on this kind of work: up to 20,000ร faster than class-validator on union-heavy structures, and notably the only one of the popular libraries that correctly handles arbitrary unions.
Measured on AMD Ryzen 9 7940HS, Rog Flow x13ย
| Components | typia | TypeBox | ajv | io-ts | zod | C.V. |
|---|---|---|---|---|---|---|
| Easy to use | โ | โ | โ | โ | โ | โ |
| Object (simple)ย | โ | โ | โ | โ | โ | โ |
| Object (hierarchical)ย | โ | โ | โ | โ | โ | โ |
| Object (recursive)ย | โ | โ | โ | โ | โ | โ |
| Object (union, implicit)ย | โ | โ | โ | โ | โ | โ |
| Object (union, explicit)ย | โ | โ | โ | โ | โ | โ |
| Object (additional tags)ย | โ | โ | โ | โ | โ | โ |
| Object (template literal types)ย | โ | โ | โ | โ | โ | โ |
| Object (dynamic properties)ย | โ | โ | โ | โ | โ | โ |
| Array (rest tuple)ย | โ | โ | โ | โ | โ | โ |
| Array (hierarchical)ย | โ | โ | โ | โ | โ | โ |
| Array (recursive)ย | โ | โ | โ | โ | โ | โ |
| Array (recursive, union)ย | โ | โ | โ | โ | โ | โ |
| Array (R+U, implicit)ย | โ | โ | โ | โ | โ | โ |
| Array (repeated)ย | โ | โ | โ | โ | โ | โ |
| Array (repeated, union)ย | โ | โ | โ | โ | โ | โ |
| Ultimate Union Type | โ | โ | โ | โ | โ | โ |
C.V.meansclass-validator.
Where to go next
- Need an error path or to throw instead of returning a boolean โ
assert - Need every error at once for a form, not just the first โ
validate - Want to constrain values (formats, ranges, lengths) โ Special Tags