Skip to main content

ComplexType

Package: @opra/common

ComplexType is the runtime class that represents an object type in an OPRA document. When you retrieve a type from an ApiDocument via document.node.getDataType(), the returned instance is a ComplexType (or one of its siblings). You interact with it to inspect fields, traverse inheritance, generate codecs, and export schema.

The @ComplexType() decorator (used on TypeScript classes) is documented in the HTTP API and Schema sections — this page covers the class itself.


Inheritance

DocumentElement
└── DataType
└── ComplexTypeBase
└── ComplexType

ComplexTypeBase holds all field-related methods and is also the base of MappedType and MixinType. ComplexType adds the base reference, discriminator fields, and the extendsFrom() check.


Properties

Properties inherited from DataType:

PropertyTypeDescription
kind'ComplexType'Always 'ComplexType'.
namestring | undefinedRegistry name. undefined for embedded (anonymous) types.
descriptionstring | undefinedHuman-readable description.
abstractboolean | undefinedWhether the type is abstract.
embeddedbooleantrue when the type has no name.
scopePattern(string | RegExp)[] | undefinedScopes this type is visible in.
examplesDataTypeExample[] | undefinedExample values.
ownerDocumentElementThe document element that owns this type.
nodeApiDocumentNodeThe root document node (used for type lookup).

Properties on ComplexTypeBase:

PropertyTypeDescription
keyFieldstring | undefinedName of the primary key field.
additionalFieldsboolean | DataType | ['error'] | ['error', string] | undefinedHow undeclared fields are handled during validation.
ctorType | undefinedThe TypeScript class constructor registered for this type.

Properties on ComplexType:

PropertyTypeDescription
baseComplexType | MappedType | MixinType | undefinedThe base type this type extends.
discriminatorFieldstring | undefinedField used to discriminate subtypes.
discriminatorValuestring | undefinedThis type's discriminator value.

Field methods

All field methods are defined on ComplexTypeBase and inherited by ComplexType.

findField(nameOrPath, scope?)

Returns the ApiField at the given name or dot-separated path, or undefined if not found. Respects scope filtering.

const field = customerType.findField('address.city');
const field = customerType.findField('email', 'admin'); // only returns the field if it is visible in the 'admin' scope
findField(nameOrPath: string, scope?: string | '*'): ApiField | undefined

getField(nameOrPath, scope?)

Same as findField but throws if the field does not exist or is out of scope.

getField(nameOrPath: string, scope?: string): ApiField

fields(scope?)

Returns an iterator over all ApiField instances visible in the given scope. Pass '*' to include all fields regardless of scope.

for (const field of customerType.fields()) {
console.log(field.name, field.type.name);
}

// All fields, ignoring scope
for (const field of customerType.fields('*')) { }
fields(scope?: string): IterableIterator<ApiField>

fieldNames(scope?)

Returns an iterator over field names only.

fieldNames(scope?: string): IterableIterator<string>

fieldEntries(scope?)

Returns an iterator over [name, ApiField] pairs.

fieldEntries(scope?: string): IterableIterator<[string, ApiField]>

fieldCount(scope?)

Returns the number of fields visible in the given scope.

fieldCount(scope?: string): number

Inheritance methods

extendsFrom(baseType)

Returns true if this type extends from the given type (directly or transitively).

customerType.extendsFrom(Person) // true if Customer extends Person
customerType.extendsFrom('Person') // by name
customerType.extendsFrom(personInstance) // by ComplexType instance
extendsFrom(baseType: DataType | string | Type | object): boolean

Scope methods

inScope(scope?)

Returns true if this type is visible in the given scope (based on scopePattern). Types without a scopePattern are always in scope.

inScope(scope?: string | '*'): boolean

Field path utilities

parseFieldPath(fieldPath, options?)

Resolves a dot-separated field path against this type's field tree. Returns an array of ParsedFieldPath items — one per path segment — each containing the resolved field, dataType, and optional sign (+/-).

const segments = customerType.parseFieldPath('address.city');
// [{ fieldName: 'address', field: ..., dataType: AddressType }, { fieldName: 'city', field: ..., dataType: StringType }]
parseFieldPath(
fieldPath: string,
options?: { allowSigns?: 'first' | 'each'; scope?: string | '*' }
): ComplexType.ParsedFieldPath[]

normalizeFieldPath(fieldPath, options?)

Resolves a field path and returns the canonical dot-separated string (with optional sign prefix per segment).

normalizeFieldPath(
fieldPath: string,
options?: { allowSigns?: 'first' | 'each'; scope?: string }
): string

Codec generation

generateCodec(codec, options?)

Compiles a validation/transformation function for either encoding (output) or decoding (input) against this type's field schema. Used internally by adapters — call this when you need a validator outside the request lifecycle.

const decoder = customerType.generateCodec('decode', { scope: 'public' });
const result = decoder(rawInput);

const encoder = customerType.generateCodec('encode', { partial: true });
generateCodec(
codec: 'encode' | 'decode',
options?: DataType.GenerateCodecOptions
): Validator

Key codec options:

OptionTypeDescription
scopestringOnly include fields visible in this scope.
partialboolean | 'deep'All fields become optional. 'deep' applies recursively.
projectionstring[] | '*'Field projection — include/exclude specific fields.
ignoreReadonlyFieldsbooleanStrip readonly fields (for input decoding).
ignoreWriteonlyFieldsbooleanStrip writeonly fields (for output encoding).
keepKeyFieldsbooleanAlways include the key field regardless of other options.
allowNullOptionalsbooleanAccept null in place of absent optional fields.

Serialization

toJSON(options?)

Returns an OpraSchema.ComplexType plain object for schema export. Called automatically during document serialization.

toJSON(options?: ApiDocument.ExportOptions): OpraSchema.ComplexType

Obtaining a ComplexType instance

You do not construct ComplexType directly. Retrieve it from a document:

import { ComplexType } from '@opra/common';

const customerType = document.node.getDataType('Customer');
// or with type guard:
if (customerType instanceof ComplexType) {
for (const field of customerType.fields()) {
console.log(field.name);
}
}

ApiDocument · ApiField