Outline
export function TypedBody(): ParameterDecorator;
Request body decorator 20,000x faster, even easy to use.
@TypedBody()
is a decorator function parsing application/json
typed request body, and validates the request body value type through typia.assert<T>()
function. If the request body is not following the promised type, 400 bad request error would be thrown.
It is almost same with original @Body()
function of NestJS
, however, 20,000x faster.
Also, @TypedBody()
is much more easier to use than class-validator
, because it can use pure TypeScript type. If you canβt understand the word βpure TypeScript typeβ, then move to below #How to use section and read the IBbsArticle.IUpdate
interface type. You may understand what it means.
If you want other Content-Type
, use one of below:
application/x-www-form-urlencoded
:@TypedQuery.Body()
.multipart/form-data
:@TypedFormData.Body()
@TypedBody()
is not essential for Swagger Documents or SDK Library building.
Therefore, it is not a matter to use @TypedBody()
or @Body()
of the original NestJS.
How to use
import { TypedBody, TypedRoute } from "@nestia/core";
import { Controller } from "@nestjs/common";
import { tags } from "typia";
import { IBbsArticle } from "./IBbsArticle";
@Controller("bbs/articles")
export class BbsArticlesController {
@TypedRoute.Post()
public async store(
@TypedBody() input: IBbsArticle.IStore,
): Promise<IBbsArticle> {
return {
...input,
id: "2b5e21d8-0e44-4482-bd3e-4540dee7f3d6",
created_at: "2023-04-23T12:04:54.168Z",
};
}
}
Just call @TypedBody()
function on the request body parameter, thatβs all.
Nestia
will analyze your type (IBbsArticle.IUpdate
), and writes optimal code for the target type, in the compilation level. If you click the βComplied JavaScript Fileβ tab of above, you can see the optimal validation code.
Such optimization is called AOT (Ahead of Time) compilation, and it is the secret of @TypedBody
.
Special Tags
You can enhance validation logic, of @TypedBody()
, through special tags.
You know what? @TypedBody()
utilizes typia.assert<T>()
function for request body data validation, and the typia.assert<T>()
function supports additional type checking logics through type and comment tags. For reference, βType Tagβ means a intersection type with atomic type and special tag type of typia
like number & tags.Type<"uint32">
, and βComment Tagβ means a comment starting from @
symbol following @${name} ${value}
format.
With those type and comment tags, you can add additional validation logics. If you want to add a custom validation logic, you also can do it. Read below Guide Docments of typia, and see the example code. You may understand how to utilize such type and comment tags, in a few minutes.
import typia, { tags } from "typia";
export const checkSpecialTag = typia.createIs<SpecialTag>();
interface SpecialTag {
int32: number & tags.Type<"int32">;
range?: number & tags.ExclusiveMinimum<19> & tags.Maximum<100>;
minLength: string & tags.MinLength<3>;
pattern: string & tags.Pattern<"^[a-z]+$">;
date: null | (string & tags.Format<"date">);
ip: string & (tags.Format<"ipv4"> | tags.Format<"ipv6">);
uuids: Array<string & tags.Format<"uuid">> &
tags.MinItems<3> &
tags.MaxItems<100>;
}
EncryptedBody
Encrypted request body decorator function.
@EncryptedBody()
is a decorator function similar with @TypedBody()
, but it encrypts the request body through AES-128/256-CBC algorithm like below. Therefore, it would be slower than @TypedBody()
, but it guarantees the security of request body data.
- AES-128/256
- CBC mode
- PKCS #5 Padding
- Base64 Encoding
For reference, such encryption spec is not supported in the Swagger-UI. Instead, SDK (Software Development Kit) generated by @nestia/sdk
supports it. Thus, you have to build and distribute the SDK library to the client developers when using such encryption decorators.
Configuration
{
"compilerOptions": {
"strict": true,
"plugins": [
{ "transform": "typia/lib/transform" },
{
"transform": "@nestia/core/lib/transform",
"validate": "assert",
// "llm": {
// "model": "chatgpt",
// "strict": true,
// },
}
]
}
}
Change type validation function to another one.
If you configure validate
property of plugin defined in the tsconfig.json
file, you can change the @TypedBody()
to use another validation function instead of the default typia.assert<T>
function. For example, if you want to use typia.validateEquals<T>()
function instead, then set the validate
property to validateEquals
.
Below is the list of available validation functions.
is
orequals
: check validation only, and do not reveal the reason whyassert
orassertEquals
: find the 1st type error with reasonvalidate
orvalidateEquals
: find every type errors with detailed reasonsassertPrune
orvalidatePrune
: prune extra properties with type checkingassertClone
orvalidateClone
: deep clone with type checking for faster pruning
Also, if you configure llm
property of the plugin, @nestia/core
considers that your backend application has been developed for LLM function calling, and validates the request/response body types following the target LLM modelβs restrictions.
For example, if you configure chatgpt
with strict
option, dynamic properties and optional properties are not allowed in the request/response body types. If your some request/response body types are not following the target LLM modelβs restrictions, @nestia/core
will throw a compilation error.
Here is the list of available LLM models. Read their definitions, and follow their restrictions.
- Supported schemas
"chatgpt"
: (IChatGptSchema
), OpenAI ChatGPT"claude"
: (IClaudeSchema
), Anthropic Claude"gemini"
: (IGeminiSchema
), Google Gemini"llama"
: (ILlamaSchema
), Meta Llama
- Midldle layer schemas
"3.0"
: (ILlmSchemaV3
), middle layer based on OpenAPI v3.0 specification"3.1"
: (ILlmSchemaV3_1
), middle layer based on OpenAPI v3.1 specification
Benchmark
Super-fast and super-safe.
Nestia
utilizes typia, and NestJS
uses class-validator
. One thing amazing is, typia
is maximum 20,000x faster than class-validator
of NestJS
. Color of class-transformer
is skyblue, and can you find the skyblue color in the below benchmark graph? It may hard to find because class-validator
is extremely slow.
Measured on AMD R9-7940HS, Rog Flow X13
Furthermore, while other libraries canβt validate complicate union types, typia
can validate every TypeScript types. However, in the class-validator
case, it always be failed when any type of complicate comes. I canβt understand why NestJS
has adopted such slow and unstable library.
Moreover, only typia
can utilize pure TypeScript type, without any extra schema definition. Beside, all of other libraries require extra and duplicated schema definition, different with pure TypeScript type. Nestia
is using such wonderful, super-fast and super-fast typia
library.
TypeBox
requiresTypeBox
schemaajv
requires JSON schema definitionio-ts
requiresio-ts
schemazod
requireszod
schemaclass-validator
requires DTO class with decorator function calls
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) | β | β | β | β | β | β |
Ultimate Union Type | β | β | β | β | β | β |
C.V.
meansclass-validator