Typia is a TypeScript validation library that transforms your TypeScript types into super-fast validation functions.
Instead of writing separate schemas like other validation libraries, Typia reads your existing TypeScript types and creates optimized validation code at compile time.
This guide will show you how to use Typia in your TypeScript projects. You'll learn how to set it up, create validation functions, handle errors, and integrate it with web frameworks.
Let's get started!
Prerequisites
Before you start with Typia, make sure you have a recent version of Node.js and npm
installed. You should also know TypeScript basics since Typia only works with TypeScript projects.
Setting up the project environment
Setting up Typia is significantly easier as it includes an automated setup wizard. The wizard handles all configuration for you, so you don't need to edit configuration files or manually install dependencies.
Create a new directory and navigate into it:
mkdir typia-validation && cd typia-validation
Initialize your project:
npm init -y
Install Typia and run the automated setup:
npm install typia
npx typia setup
----------------------------------------
Typia Setup Wizard
----------------------------------------
? Package Manager npm
$ npm i -D typescript@~5.8.3
...
$ npm i -D ts-patch@latest
...
$ npx tsc --init
Created a new tsconfig.json with:
TS
target: es2016
module: commonjs
strict: true
esModuleInterop: true
skipLibCheck: true
forceConsistentCasingInFileNames: true
You can learn more at https://aka.ms/tsconfig
$ npm run prepare
> typia-validation@1.0.0 prepare
> ts-patch install
[+] ts-patch installed!
The setup wizard automatically handles everything for you:
- Installs required dependencies (
typescript
,ts-patch
) - Configures your
tsconfig.json
with the right settings - Sets up the transformer plugin
- Adds the necessary npm scripts
That's it! Typia can now transform your TypeScript types into optimized validation functions during code compilation.
Understanding Typia's fundamentals
Typia works differently from other validation libraries. Instead of defining schemas, you just use regular TypeScript interfaces and types. Typia reads these types when you compile your code and generates super-fast validation functions.
Create a validation.ts
file in your project:
import typia from "typia";
interface User {
name: string;
age: number;
email: string;
}
export const validateUser = typia.createValidate<User>();
export const checkUser = typia.createIs<User>();
This code defines a simple User
interface and creates two validation functions:
validateUser
: Returns detailed results with error information if validation failscheckUser
: Returnstrue
orfalse
to tell you if the data is valid
Now create an index.ts
file to test these validators:
import { validateUser, checkUser } from './validation';
const userData = {
name: 'Alice',
age: 25,
email: 'alice@example.com',
};
// Simple boolean check
const isValid = checkUser(userData);
console.log('Is valid:', isValid);
// Detailed validation with error info
const validationResult = validateUser(userData);
if (validationResult.success) {
console.log('Valid user data:', validationResult.data);
} else {
console.error('Validation errors:', validationResult.errors);
}
The checkUser
function gives you a simple yes/no answer. The validateUser
function gives you detailed information. When the data matches your User
interface, validateUser
returns a success object with the validated data. When validation fails, it returns specific error information showing exactly what went wrong.
Add the build script to your package.json
:
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepare": "ts-patch install",
"build": "tsc"
}
}
Compile and run the application:
npm run build
node index.js
With valid input data, you'll see:
Is valid: true
Valid user data: { name: 'Alice', age: 25, email: 'alice@example.com' }
Here's what makes Typia helpful: when you compile your code, Typia transforms your validation functions into highly optimized JavaScript. The typia.createIs<User>()
call becomes a specific function that directly checks for string and number types without any runtime overhead.
Validation with special tags
Typia lets you add validation rules that go beyond basic type checking. You do this using special tags that work with TypeScript's intersection types. These tags let you express complex validation logic while keeping your code type-safe.
Adding validation constraints
You can add specific validation rules using Typia's built-in tags. Update your validation.ts
file:
import typia, { tags } from "typia";
interface User {
name: string & tags.MinLength<3> & tags.MaxLength<50>;
age: number & tags.Type<"uint32"> & tags.ExclusiveMinimum<18> & tags.Maximum<120>;
email: string & tags.Format<"email">;
password: string & tags.MinLength<8> & tags.Pattern<"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).+$">;
}
export const validateUser = typia.createValidate<User>();
Each tag adds a specific rule:
tags.MinLength<3>
andtags.MaxLength<50>
: The name must be between 3 and 50 characterstags.Type<"uint32">
: The age must be a positive integer within 32-bit rangetags.ExclusiveMinimum<18>
: The age must be greater than 18 (not equal to 18)tags.Format<"email">
: The email must be in valid email formattags.Pattern<"...">
: The password must match the regex pattern (requires numbers, lowercase, and uppercase letters)
Test these rules with invalid data in your index.ts
:
import { validateUser } from "./validation";
const invalidUserData = {
name: "Al", // Too short
age: 17, // Too young
email: "not-an-email", // Invalid format
password: "weak", // Too simple
};
const result = validateUser(invalidUserData);
if (!result.success) {
console.error("Validation errors:");
result.errors.forEach((error) => {
console.log(` ${error.path}: ${error.expected}`);
});
}
With the invalid data in place, run the script:
npm run build
node index.js
Running this code shows you specific error messages:
Validation errors:
$input.name: string & MinLength<3>
$input.age: number & ExclusiveMinimum<18>
$input.email: string & Format<"email">
$input.password: string & MinLength<8>
Typia's error reporting tells you exactly which fields failed and why, making it easy to fix problems or show helpful error messages to users.
When you need validation rules that aren't built into Typia, you can create custom tags using the tags.TagBase
interface:
import typia, { tags } from "typia";
// Custom tag for currency validation
type Currency = tags.TagBase<{
kind: "currency";
target: "string";
value: undefined;
validate: `$input.match(/^\\$\\d+(\\.\\d{2})?$/) !== null`;
}>;
// Custom tag for even numbers
type EvenNumber = tags.TagBase<{
kind: "even";
target: "number";
value: undefined;
validate: `$input % 2 === 0`;
}>;
interface Product {
name: string & tags.MinLength<1>;
price: string & Currency;
quantity: number & tags.Type<"uint32"> & EvenNumber;
}
export const validateProduct = typia.createValidate<Product>();
Custom tags work by defining JavaScript code in the validate
property. Typia injects this code into the generated validation function. The $input
variable represents the value being checked, and your validation code should return true
for valid values or false
for invalid ones.
Combining multiple validation rules
Typia does well at combining multiple validation rules into comprehensive type definitions. You can create complex validation schemas by chaining tags together:
interface BlogPost {
title: string & tags.MinLength<5> & tags.MaxLength<200>;
content: string & tags.MinLength<100>;
tags: Array<string & tags.MinLength<2> & tags.MaxLength<20>> & tags.MinItems<1> & tags.MaxItems<10>;
publishedAt: string & tags.Format<"date-time">;
status: "draft" | "published" | "archived";
metadata: {
author: string & tags.Format<"uuid">;
category: string & tags.Pattern<"^[a-z-]+$">;
readingTime: number & tags.Type<"uint32"> & tags.Minimum<1>;
};
}
This schema shows how Typia handles nested objects, arrays with item constraints, union types, and complex validation combinations. The validation function checks every constraint efficiently while providing detailed error information when validation fails.
Integrating Typia with Express
Typia fits naturally into backend frameworks like Express, where validating request bodies is a common task. You can use Typia to validate incoming data before your route handlers process it, ensuring type safety from the API boundary all the way through your application.
Start by installing Express and its TypeScript types:
npm install express
npm install --save-dev @types/express@4 @types/node
Let's use our existing User
interface from the validation file. Make sure your validation.ts
looks like this:
import typia from "typia";
interface User {
name: string;
age: number;
email: string;
}
export const validateUser = typia.createValidate<User>();
Now create a basic server in a new file called server.ts
:
import express from "express";
import { validateUser } from "./validation";
const app = express();
app.use(express.json());
app.post("/users", (req, res) => {
console.log("Received request body:", req.body);
const result = validateUser(req.body);
if (!result.success) {
console.log("Validation failed");
return res.status(400).json({
message: "Validation failed",
errors: result.errors.map((e) => ({
field: e.path.replace("$input.", ""),
expected: e.expected,
received: e.value,
})),
});
}
console.log("Validation successful");
res.status(201).json({
message: "User created successfully",
data: result.data,
});
});
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
In this example, Typia validates the incoming JSON against the User
interface. If the data is invalid, the API responds with clear error messages. If validation passes, it proceeds with the validated data.
Build and run the server:
npm run build
node server.js
You should see:
Server running on http://localhost:3000
Now test the API with valid data using curl (in a new terminal):
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "age": 30, "email": "alice@example.com"}'
Or use Postman:
You'll get a success response:
{
"message": "User created successfully",
"data": {
"name": "Alice",
"age": 30,
"email": "alice@example.com"
}
}
Now test with invalid data to see how Typia handles validation errors:
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name": "Bob", "age": "twenty-five", "email": 12345}'
Or in Postman:
You'll get a validation error response:
{
"message": "Validation failed",
"errors": [
{
"field": "age",
"expected": "number",
"received": "twenty-five"
},
{
"field": "email",
"expected": "string",
"received": 12345
}
]
}
The server console will show:
Received request body: { name: 'Bob', age: 'twenty-five', email: 12345 }
Validation failed
Typia makes it clear where the data doesn’t match the expected type, helping you catch issues early and respond with helpful errors.
Final thoughts
Typia helps you validate data using your existing TypeScript types. It keeps your code simple, boosts performance by generating optimized validation functions at build time, and provides detailed error messages when something doesn’t match.
You can learn more in the Typia documentation or explore the source on GitHub.
Make your mark
Join the writer's program
Are you a developer and love writing and sharing your knowledge with the world? Join our guest writing program and get paid for writing amazing technical guides. We'll get them to the right readers that will appreciate them.
Write for us
Build on top of Better Stack
Write a script, app or project on top of Better Stack and share it with the world. Make a public repository and share it with us at our email.
community@betterstack.comor submit a pull request and help us build better products for everyone.
See the full list of amazing projects on github