@tsed/schema
Version:
JsonSchema module for Ts.ED Framework
107 lines (106 loc) • 2.99 kB
JavaScript
import { useDecorators } from "@tsed/core";
import { JsonSchema } from "../../domain/JsonSchema.js";
import { array } from "../../fn/collection.js";
import { JsonEntityFn } from "./jsonEntityFn.js";
import { OneOf } from "./oneOf.js";
import { Property } from "./property.js";
/**
* Marks a property as nullable, allowing it to accept `null` in addition to its base type.
*
* The `@Nullable()` decorator creates a union type that includes `null` alongside the
* specified type(s). This is implemented using JSON Schema's `oneOf` keyword to allow
* either the specified type or null.
*
* ### Single Type with Null
*
* ```typescript
* class UserModel {
* @Nullable(Date)
* lastLogin: Date | null;
* // Accepts: Date object OR null
* }
* ```
*
* ### Multiple Types with Null
*
* ```typescript
* class FlexibleModel {
* @Nullable(String, Number, Boolean)
* property: string | number | boolean | null;
* // Accepts: string OR number OR boolean OR null
* }
* ```
*
* ### With Custom Classes
*
* ```typescript
* class Address {
* @Property()
* street: string;
* }
*
* class Person {
* @Nullable(Address)
* address: Address | null;
* // Accepts: Address object OR null
* }
* ```
*
* ### TypeScript Integration
*
* ```typescript
* class Product {
* @Nullable(String)
* description: string | null;
*
* @Nullable(Number)
* discount: number | null;
* }
* ```
*
* ### Important: Arrays
*
* Do NOT use `@Nullable(Array)` as it produces incorrect schemas. Instead:
*
* ```typescript
* // Wrong
* @Nullable(Array)
* items: any[] | null;
*
* // Correct
* @Schema(array().items().nullable())
* items: any[] | null;
* ```
*
* ### Use Cases
*
* - **Optional Database Fields**: Model nullable database columns
* - **Partial Updates**: Allow fields to be explicitly set to null in PATCH requests
* - **Default Values**: Distinguish between "not provided" and "explicitly null"
* - **External APIs**: Match nullable fields from third-party services
*
* ### vs Optional
*
* - `@Nullable()`: Field can be present with value `null`
* - `@Optional()`: Field can be omitted entirely
* - Can combine both: `@Optional() @Nullable(String)` allows omitted, null, or string
*
* @param type - The primary type that can be null
* @param types - Additional types that can be null (creates multi-type union with null)
*
* @decorator
* @validation
* @public
*/
export function Nullable(type, ...types) {
types = [type, ...types];
if (type === Array) {
return JsonEntityFn((entity) => {
entity.schema.assign(array()
.items({})
.$comment("Warning: you should not use @Nullable(Array), which leads to an incorrect schema. Use @Schema(array().items().nullable()) instead")
.nullable(true));
});
}
return useDecorators(types.length === 1 && !(type instanceof JsonSchema) && Property(types[0]), OneOf(null, ...types));
}