assert()
function
export function assert<T>(input: T): T;
export function assert<T>(input: unknown): T;
Asserts a value type.
typia.assert<T>()
function throws a TypeGuardError
when wrong type comes.
The TypeGuardError
instance has only the first type error info, with access path and expected type. In the below example case, as the age
property is wrong with its definition (@exclusiveMinimum
), such TypeGuardError
would be thrown:
method
:typia.assert()
path
:input.age
value
:18
,expected
:number & ExclusiveMinimum<19>
import typia, { tags } from "typia";
import { v4 } from "uuid";
typia.assert<IMember>({
id: v4(),
email: "samchon.github@gmail.com",
age: 18, // wrong, must be greater than 19
});
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}
assertEquals()
function
export function assertEquals<T>(input: T): T;
export function assertEquals<T>(input: unknown): T;
More strict assert function prohibiting superfluous properties.
typia.assert<T>()
function inspects input
value type and throws TypeGuardError
when mismatched, however, it canβt detect superfluous properties. If you want to prohibit those superfluous properties, therefore throws an TypeGuardError
when superfluous property exists, use typia.assertEquals<T()>
function instead.
In the below example case, as sex
property is not defined in the IMember
type, such TypeGuardError
would be thrown:
method
:typia.assertEquals()
path
:input.sex
value
:1
,expected
:undefined
import typia, { tags } from "typia";
import { v4 } from "uuid";
typia.assert<IMember>({
id: v4(),
email: "samchon.github@gmail.com",
age: 30,
sex: 1, // extra
});
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}
assertGuard()
functions
export function assertGuard<T>(input: T): asserts input is T;
export function assertGuard<T>(input: unknown): asserts input is T;
export function assertGuardEquals<T>(input: T): asserts input is T;
export function assertGuardEquals<T>(input: unknown): asserts input is T;
Assertion guard of a value type.
typia.assertGuard<T>()
is similar with typia.assert<T>()
throwing a TypeGuardError
when wrong type.
However, typia.assert<T>()
returns the paramteric input value itself when thereβs no type problem on the parametric input value, whereas the typia.assertGuard<T>()
function returns nothing. Instead, the parametric input value would be automatically cased to the type T
. This is the concept of βAssertion Guardβ of a value type.
Such similarities and differences of typia.assertGuard<T>()
and typia.assert<T>()
functions are the same in the case of typia.assertGuardEquals<T>()
and typia.assertEquals<T>()
functions. If thereβs no type problem on the typia.assertGuardEquals<T>()
function, it also performs the βAssertion Guardβ.
Look at the below code, then you may understand what the βAssertion Guardβ means.
import typia from "typia";
interface IPoint {
x: number;
y: number;
}
const input: unknown = { x: 1, y: 2 };
// PERFORM THE ASSERTION GUARD
typia.assertGuard<IPoint>(input);
// FROM NOW ON, "input" IS THE "IPoint" TYPE
input.x; // OK
input.y; // OK
Reusable functions
export function createAssert<T>(): (input: unknown) => T;
export function createAssertEquals<T>(): (input: unknown) => T;
export function createAssertGuard<T>(): AssertionGuard<T>;
export function createAssertGuardEquals<T>(): AssertionGuard<T>;
Reusable typia.assert<T>()
function generators.
If you repeat to call typia.assert<T>()
function on the same type, size of JavaScript files would be larger because of duplicated AOT compilation. To prevent it, you can generate reusable function through typia.createAssert<T>()
function.
Just look at the code below, then you may understand how to use it.
import typia, { tags } from "typia";
export const assertMember = typia.createAssert<IMember>();
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}
Restrictions
typia.assert<T>()
function does not check function
and user-defined class
types.
It validates only the primitive properties. Therefore, typia.assert<T>()
function does not perform the instanceof ClassName
for user-defined classes. If you want to validate the user-defined class type in addition to the property types, do it by yourself. Also, typia.assert<T>()
function does not validate the function type either, unless configuring functional
property of plugin
option in the tsconfig.json
file.
{
"compilerOptions": {
"plugins": [
{
"transform": "typia/lib/transform",
"functional": true
}
]
}
}
By the way, thereβre some exception cases.
If JS native class type like Date
, Uint8Array
, or Map<Key, T>
being utilized, typia.assert<T>()
function validates them. Especially about the Set<T>
, and Map<Key, T>
class cases, typia.assert<T>()
function validates all of their contained element types, too.
Therefore, the instanceof
statement does not be used only for the user-defined classes.
import typia from "typia";
typia.createIs<Map<string, boolean | number | string>>();
Customization
You can enhance validation logic by special tags.
Also, with those tags, you can add your custom validation logic, too.
If you want to know about such special tags detaily, read below article:
import typia, { tags } from "typia";
export const assertSomething = typia.createAssert<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>;
}
Performance
Super-fast and super-safe.
Comparing typia.assert<T>()
function with other competitive libraries, maximum 20,000x faster.
Furthermore, only typia
can validate complicate union types.
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