validate() function
undefined
export function validate<T>(input: T): IValidation<T>;
export function validate<T>(input: unknown): IValidation<T>;Validates a value type.
typia.validate<T>() function validates input value type, and archives every type errors detaily into IValidation.IFailure.errors array, when the input value is not following the promised type T. Of course, if the parametric input value is following the type T, IValidation.ISuccess instance would be returned.
In the below example case, as id and age values are different with its definition of IMember, such errors would be archived into the IValidation.IFailure.errors array.
errors[0]path:input.idexpected:string & Format<"uuid">value: 5
errors[1]path:input.ageexpected:number & Format<"uint32">value: 20.75
TypeScript Source Code
import typia, { tags } from "typia";
const res: typia.IValidation<IMember> = typia.validate<IMember>({
id: 5, // wrong, must be string (uuid)
age: 20.75, // wrong, not integer
email: "samchon.github@gmail.com",
});
if (res.success === false) console.log(res.errors);
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}validateEquals() function
undefined
export function validateEquals<T>(input: T): IValidation<T>;
export function validateEquals<T>(input: unknown): IValidation<T>;More strict validate function prohibiting superfluous properties.
typia.validate<T> function detects every type errors of input value, however, it can’t detect superfluous properties. If you want to prohibit those superfluous properties, so that archive them into IValidation.IFailure.errors array, use typia.validateEquals<T>() function instead.
In the below example case, as id property is different with its type definition and sex property is not defined in the IMember type, such errors would be archived into the IValidation.IFailure.errors array:
errors[0]path:input.idexpected:string (@format uuid)value:something
errors[1]path:input.sexexpected:undefinedvalue:1
TypeScript Source Code
import typia, { tags } from "typia";
const res: typia.IValidation<IMember> = typia.validateEquals<IMember>({
age: 30,
email: "samchon.github@gmail.com",
id: "something", // wrong, must be string (uuid)
sex: 1, // extra property
});
if (res.success === false) console.log(res.errors);
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}Reusable functions
undefined
export function createValidate<T> = (input: unknown) => IValidation<T> & StandardSchemaV1<T, T>;
export function createValidateEquals<T> = (input: unknown) => IValidation<T> & StandardSchemaV1<T, T>;Reusable typia.validate<T>() function generators.
If you repeat to call typia.validate<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.createValidate<T>() function.
Just look at the code below, then you may understand how to use it.
TypeScript Source Code
import typia, { tags } from "typia";
export const validateMember = typia.createValidate<IMember>();
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}This reusable function implements Standard Schema interface. Therefore, you can use this function with a library which accepts Standard Schema interface , such as upfetch :
import typia from "typia";
import { up } from "up-fetch";
const upfetch = up(fetch);
const schema = typia.createValidate<ISmallTodo>();
// passes
await upfetch("https://jsonplaceholder.typicode.com/todos/1", {
schema,
});
// fails
await upfetch("https://jsonplaceholder.typicode.com/todos/10", {
schema,
})
interface ISmallTodo {
userId: number;
/** @maximum 5 */
id: number;
title: string;
completed: boolean;
}Restrictions
typia.validate<T>() function does not check function and user-defined class types.
It validates only the primitive properties. Therefore, typia.validate<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.validate<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.validate<T>() function validates them. Especially about the Set<T>, and Map<Key, T> class cases, typia.validate<T>() function validates all of their contained element types, too.
Therefore, the instanceof statement does not be used only for the user-defined classes.
TypeScript Source Code
import typia from "typia";
typia.createIs<Map<string, boolean | number | string>>();Discriminated Union
undefined
/**
* Validation result type with detailed error information.
*
* `IValidation<T>` is the return type of `typia.validate<T>()` and related
* validation functions. Unlike `typia.is<T>()` which returns a boolean, or
* `typia.assert<T>()` which throws exceptions, `typia.validate<T>()` returns
* this structured result with full error details.
*
* Check the {@link IValidation.success | success} discriminator:
*
* - `true` → {@link IValidation.ISuccess} with validated
* {@link IValidation.ISuccess.data | data}
* - `false` → {@link IValidation.IFailure} with
* {@link IValidation.IFailure.errors | errors} array
*
* This is the recommended validation function when you need to report
* validation errors to users or log them for debugging.
*
* @author Jeongho Nam - https://github.com/samchon
* @example
* const result = typia.validate<User>(input);
* if (result.success) {
* return result.data; // User type
* } else {
* result.errors.forEach((e) => console.log(e.path, e.expected));
* }
*
* @template T The expected type after successful validation
*/
export type IValidation<T = unknown> =
| IValidation.ISuccess<T>
| IValidation.IFailure;
export namespace IValidation {
/**
* Successful validation result.
*
* Indicates the input matches the expected type. The validated data is
* available in {@link data} with full type information.
*
* @template T The validated type
*/
export interface ISuccess<T = unknown> {
/**
* Success discriminator.
*
* Always `true` for successful validations. Use this to narrow the type
* before accessing {@link data}.
*/
success: true;
/**
* The validated data with correct type.
*
* The original input after successful validation. TypeScript will narrow
* this to type `T` when {@link success} is `true`.
*/
data: T;
}
/**
* Failed validation result with error details.
*
* Indicates the input did not match the expected type. Contains the original
* data and an array of all validation errors found.
*/
export interface IFailure {
/**
* Success discriminator.
*
* Always `false` for failed validations. Use this to narrow the type before
* accessing {@link errors}.
*/
success: false;
/**
* The original input that failed validation.
*
* Preserved as `unknown` type since it didn't match the expected type.
* Useful for debugging or logging the actual value.
*/
data: unknown;
/**
* Array of validation errors.
*
* Contains one entry for each validation failure found. Multiple errors may
* exist if the input has multiple type mismatches.
*/
errors: IError[];
}
/**
* Detailed information about a single validation error.
*
* Describes exactly what went wrong during validation, including the
* location, expected type, and actual value.
*/
export interface IError {
/**
* Property path to the error location.
*
* A dot-notation path from the root input to the failing property. Uses
* `$input` as the root. Example: `"$input.user.email"` or
* `"$input.items[0].price"`.
*/
path: string;
/**
* Expected type expression.
*
* A human-readable description of what type was expected at this location.
* Examples: `"string"`, `"number & ExclusiveMinimum<0>"`, `"(\"active\" |
* \"inactive\")"`.
*/
expected: string;
/**
* The actual value that failed validation.
*
* The value found at the error path. May be `undefined` if the property was
* missing. Useful for debugging type mismatches.
*/
value: unknown;
/**
* Human-readable error description.
*
* Optional additional context about the validation failure, such as
* constraint violations or custom error messages.
*/
description?: string;
}
}Specify type through if condition.
typia.IValidation<T> is an union type of typia.IValidation.ISuccess<T> and typia.IValidation.IFailure. Also, they have a common property success of boolean type, but different literal values. In that case, if you write a if condition about the success property, you can specify the union type like below.
In TypeScript, such union type specification through common property (of different literal value() is called “Discriminated Union”. Therefore, when using typia.validate<T>() function, let’s utilize such discriminated union specification for convenience.
import typia from "typia";
const something: unknown = ...;
const result: typia.IValidation<string> = typia.validate<string>(something);
if (results.success) {
// become typia.IValidation.Success<string> type
result.data; // accessible
} else {
// become typia.IValidation.Failure type
result.errors; //accessible
}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:
TypeScript Source Code
import typia, { tags } from "typia";
export const validateSomething = typia.createValidate<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.validate<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