If you’ve ever built a NestJS API, you’ve likely felt the “Schema Tax.” To get robust runtime validation, you usually have to define a TypeScript interface, then a Class, and then sprinkle that class with @IsString() or @IsEmail() decorators from class-validator.
You end up maintaining the same data structure in three places: the type, the class decorators, and often a manual Swagger schema. Typia changes this. It uses AOT (Ahead-of-Time) compilation to transform your pure TypeScript interfaces into ultra-fast validation logic. No decorators, no classes—just types.
Why Typia?
Before we dive into the code, here is why Typia is becoming the gold standard for performance-critical NestJS apps:
- Single Source of Truth: Your TypeScript interface is your validation schema.
- Insane Performance: It is up to 20,000x faster than class-validator because it generates optimized JavaScript code during compilation rather than scanning metadata at runtime.
- Type Safety: It supports complex TypeScript features that class-validator struggles with, like Union types, Pick/Omit, and recursive structures.
Step 1: Installation & Setup
Typia requires a TypeScript transformer to work. The easiest way to set this up in a NestJS project is using ts-patch.
Bash
npm install --save typia
npm install --save-dev typescript ts-patch ts-node
npx typia setupThis command updates your tsconfig.json to include the Typia plugin and adds a prepare script to your package.json to ensure the compiler is patched.
Step 2: Request Validation with @TypedBody
In a standard NestJS setup, you’d use ValidationPipe. With Typia, we use @nestia/core (a companion library) to handle the heavy lifting seamlessly within controllers.
First, install the core library: npm install @nestia/core
Now, let’s define a simple interface and use it in a controller:
import { Controller } from '@nestjs/common';
import { TypedBody, TypedRoute } from '@nestia/core';
import { tags } from 'typia';
interface CreateUserDto {
/**
* @format email
*/
email: string;
name: string & tags.MinLength<3>;
age: number & tags.Type<"uint32"> & tags.Minimum<18>;
}
@Controller('users')
export class UserController {
@TypedRoute.Post()
public async create(@TypedBody() input: CreateUserDto) {
return input;
}
}Note: Notice the tags. These are “Type Tags” provided by Typia to add constraints like MinLength or Minimum directly to your type definitions.
Want Faster API Validation? Talk To Our Engineers.
Step 3: Response Validation (Automatic Masking)
One of the most overlooked features is Response Validation. Often, you accidentally leak sensitive fields (like password_hash) because you returned a database object directly.
Typia’s @TypedRoute automatically generates a “Stringify” function that masks any properties not defined in your return type.
interface UserResponse {
id: string & tags.Format<"uuid">;
email: string;
}
@TypedRoute.Get(':id')
public async getUser(): Promise<UserResponse> {
return {
id: "uuid-123",
email: "test@example.com",
password_hash: "SECRET" // This will be automatically stripped from the JSON response!
};
}Step 4: Configuration Validation
Validating your process.env variables is crucial for app stability. You can use Typia’s assert or validate functions inside your ConfigService.
import typia from 'typia';
interface EnvConfig {
PORT: number & tags.Default<3000>;
DB_URL: string & tags.Format<"url">;
NODE_ENV: "development" | "production" | "test";
}
export function validateConfig(config: Record<string, any>) {
// This will throw a detailed error if process.env is missing required fields
return typia.assert<EnvConfig>(config);
}In your AppModule:
ConfigModule.forRoot({
validate: validateConfig,
}),
Conclusion
The “Schema Tax” has long slowed productivity in the NestJS ecosystem. Moving from the traditional class-and-decorator pattern to Typia improves not only performance but also the overall developer experience. When TypeScript interfaces act as the single source of truth for requests, responses, and configuration, code becomes easier to read, maintain, and scale. Developers no longer need to worry about mismatches between decorators and types if the code compiles, the validation is already in place.
This approach also reduces the risk of bugs and increases development speed. Because validation logic is generated directly from TypeScript types, the possibility of type drift where types and validators become inconsistent is removed. Developers spend less time writing repetitive decorators and more time focusing on meaningful business logic, which ultimately accelerates development cycles.
Typia also strengthens production reliability by validating environment variables and preventing accidental exposure of sensitive data in API responses. By shifting validation responsibilities to the compiler, it introduces a more efficient, type-driven workflow. For teams building high-performance NestJS APIs, Typia offers a practical way to simplify validation while improving security, maintainability, and overall performance.
































