@tsed/schema
Version:
JsonSchema module for Ts.ED Framework
91 lines (90 loc) • 2.37 kB
JavaScript
import { cleanObject } from "@tsed/core";
/**
* Manages discriminator mappings for polymorphic type resolution.
*
* A discriminator enables polymorphism in schemas by using a specific property
* value to determine which subtype schema to apply. This is essential for
* inheritance hierarchies and union types in OpenAPI specifications.
*
* ### Concept
*
* When a base class has multiple derived classes, the discriminator property
* (e.g., "type", "kind") indicates which concrete class an object represents.
*
* ### Usage
*
* ```typescript
* // Base class
* @DiscriminatorKey("type")
* abstract class Animal {
* type: string;
* }
*
* // Derived classes
* @DiscriminatorValue("dog")
* class Dog extends Animal {
* breed: string;
* }
*
* @DiscriminatorValue("cat")
* class Cat extends Animal {
* indoor: boolean;
* }
* ```
*
* ### OpenAPI Mapping
*
* Generates OpenAPI discriminator objects:
* ```json
* {
* "discriminator": {
* "propertyName": "type",
* "mapping": {
* "dog": "#/components/schemas/Dog",
* "cat": "#/components/schemas/Cat"
* }
* }
* }
* ```
*
* ### Key Features
*
* - **Type Mapping**: Maps discriminator values to TypeScript classes
* - **Bidirectional Lookup**: Find type by value or values by type
* - **Default Values**: Get the default discriminator value for a type
* - **Children Discovery**: List all derived types
*
* @public
*/
export class Discriminator {
constructor({ base, propertyName, types, values } = {}) {
this.values = new Map();
this.types = new Map();
Object.assign(this, cleanObject({
base,
propertyName,
types: types ? new Map(types) : undefined,
values: values ? new Map(values) : undefined
}));
}
add(type, values) {
values.forEach((value) => {
this.values.set(value, type);
});
this.types.set(type, values);
return this;
}
getType(discriminatorValue) {
return this.values.get(discriminatorValue) || this.base;
}
getValues(type) {
return this.types.get(type);
}
getDefaultValue(type) {
const values = this.types.get(type);
return values ? values[0] : undefined;
}
children() {
return [...new Set([...this.types.keys()])];
}
}