quickmodel / IQAdvancedOptions
Interface: IQAdvancedOptions<TTypeMap>
Advanced options for @Quick() decorator (second parameter).
Now with proper key inference from the typeMap.
See
- Quick — decorator that accepts these options as its second parameter
- IQDiscriminatorConfig — discriminator configuration type
- IQTypeGuardFunction — custom type guard function type
- Quick — decorator that accepts an
IQAdvancedOptionsas its second argument - IQDiscriminatorConfig — discriminator configuration type used within this interface
Examples
Simple discriminator by field name:
interface IContent { type: 'content'; text: string; }
interface IMetadata { type: 'metadata'; tags: string[]; }
@Quick({
items: [Content, Metadata]
}, {
discriminators: {
items: 'type' // ✅ TypeScript knows 'items' is a valid key
}
})
class Data extends QModel<IData> {
declare items: (Content | Metadata)[];
}With explicit mapping:
@Quick({
items: [Content, Metadata]
}, {
discriminators: {
items: { // ✅ TypeScript knows 'items' is a valid key
field: 'type',
mapping: {
'content': Content, // ✅ Must be Content or Metadata
'metadata': Metadata
}
}
}
})With custom type guard function (with proper type inference):
@Quick({
items: [Content, Metadata]
}, {
discriminators: {
items: (data) => {
// ✅ TypeScript knows this must return Content or Metadata
if ('text' in data) return Content;
if ('tags' in data) return Metadata;
return Content; // ✅ Fallback must also be Content or Metadata
}
}
})
``` *
## Type Parameters
### TTypeMap
`TTypeMap` *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\>
The type map passed to @Quick() (first parameter)
## Properties
### alias?
> `optional` **alias?**: `Record`\<`string`, `string`\>
Key alias map for input remapping (API → model) and output remapping (model → API).
Maps each model property name to its external alias key. During construction, alias keys
in the input are automatically renamed to the property name. During `serialize()`, property
names are renamed back to the alias keys in the output.
**Type-safe alternative to `@QAlias`**: unlike `@QAlias`, the alias map provided here is
visible to TypeScript at compile time when combined with the second generic of `QModel`.
Pass the same map as `TAliasMap` to `QModel<TInterface, TAliasMap>` so that `serialize()`
returns a correctly typed object with alias keys — enabling IDE autocomplete without casts.
#### Example
```typescript
type IUserAliases = { firstName: 'first_name'; lastName: 'last_name' };
@Quick({}, { alias: { firstName: 'first_name', lastName: 'last_name' } })
class User extends QModel<IUser, IUserAliases> {
declare firstName: string;
declare lastName: string;
}
const user = new User({ first_name: 'Alice', last_name: 'Smith' });
user.firstName; // 'Alice'
user.$qSerialize().first_name; // 'Alice' — typed correctly ✅coercionStrategy?
optionalcoercionStrategy?:"strict"|"loose"
Type coercion strategy (per-model override).
dateStrategy?
optionaldateStrategy?:"iso"|"timestamp"|"native"
Date serialization strategy.
discriminators?
optionaldiscriminators?: { [K in string | number | symbol]?: IQDiscriminatorConfig<IQExtractConstructors<TTypeMap[K]>, IQExtractValidDiscriminatorKeys<TTypeMap[K]> & string> }
Discriminator configuration for union type properties.
Maps property names to their discriminator configuration. Keys are inferred from the typeMap, and discriminator functions are typed to return only the constructors declared in the typeMap. String discriminators are validated to be common keys across all types.
- string: Field name to use as discriminator (validated against common keys)
- function: Custom type guard function (properly typed)
- object: Full configuration with field and mapping
enableDebugLogs?
optionalenableDebugLogs?:boolean
Enable internal debug logging for this model. Useful for troubleshooting transformation or validation issues.
excludeFields?
optionalexcludeFields?:string[]
Fields to permanently exclude from serialization (serialize() / toJSON()).
Useful for WeakMap/WeakSet properties, passwords, internal caches, or any field that should never appear in the output regardless of how the model is serialized.
Unlike the runtime omit option (which is per-call), excludeFields is declared once in the decorator and is always applied automatically.
Deserialization is NOT affected — the fields are still populated on the instance.
Example
@Quick({ cache: WeakMap }, { excludeFields: ['cache'] })
class Session extends QModel<ISession> {
declare id: string;
declare cache: WeakMap<object, any>; // runtime only — never in JSON
}
@Quick({}, { excludeFields: ['password', '_checksum'] })
class User extends QModel<IUser> {
declare id: number;
declare password: string; // never serialized
}exposeUnsetFields?
optionalexposeUnsetFields?:boolean
Include fields with undefined/null values in the serialized output.
- true:
key: nullorkey: undefinedare included in JSON. - false (default): Keys with undefined values are omitted (standard JSON behavior for undefined).
history?
optionalhistory?:IQHistoryClassConfig
History trail configuration for this model class.
When enabled: true, every $qPatch(), $qCopy(), and $qFrom() call records a chronological mutation log accessible via instance.$qHistory.
The constructor is not recorded — only mutations are tracked. When disabled (the default), no overhead is incurred: $qHistory returns a no-op NullHistoryHandle and the internal array is never allocated.
Example
@Quick({ name: 'string' }, { history: { enabled: true, maxEntries: 50 } })
class Contract extends QModel<IContract> {
declare name: string;
}
const c = new Contract({ name: 'v1' });
c.$qPatch({ name: 'v2' });
c.$qHistory.value;
// → [{ method: 'patch', at: Date, changes: { name: { from: 'v1', to: 'v2' } } }]See
- IQHistoryHandle — the handle returned by
$qHistory - IQHistoryEntry — shape of each entry
integrityErrorStrategy?
optionalintegrityErrorStrategy?:"failFast"|"accumulate"
Strategy for reporting integrity errors.
- failFast: Returns immediately on the first error encountered (optimized).
- accumulate (default): Collects and returns all integrity errors.
maxArrayLength?
optionalmaxArrayLength?:number
Maximum allowed length for arrays during deserialization. Overrides the global default limit for this model.
Used to mitigate DoS attacks via massive arrays.
Default
10000 (configurable via global config)mockers?
optionalmockers?: { [K in string | number | symbol]?: IQMockerFn }
Custom mock generators for specific properties.
Allows defining how to generate mock data for specific fields. Critical when using custom transformers where the default mock generation (which infers from type) might produce invalid/incompatible data.
Example
@Quick({
sku: (val) => `ITEM-${val}` // Custom transformer
}, {
mockers: {
// Generate valid SKU base for the transformer
sku: () => faker.string.alphanumeric(8)
}
})normalization?
optionalnormalization?:object
String normalization options (per-model override).
emptyStringAsNull?
optionalemptyStringAsNull?:boolean
trimStrings?
optionaltrimStrings?:boolean
nullToUndefined?
optionalnullToUndefined?:boolean
If true, converts all null values to undefined.
performance?
optionalperformance?:object
Performance optimization settings.
disableSafetyChecks?
optionaldisableSafetyChecks?:boolean
Disables redundant runtime safety checks (like Object.freeze) when data source is trusted. Use with caution.
Default
falseserializers?
optionalserializers?: { [K in string | number | symbol]?: IQSerializerFn }
Custom serializers for specific properties.
Allows defining the reverse transformation logic (Model -> Interface) for specific fields. Critical when using custom transformers that function as one-way mappings, or when the default serialization behavior needs to be overridden for specific fields.
Example
@Quick({
date: Date
}, {
transformers: {
// Deserialize: seconds -> Date
date: (val) => new Date(val * 1000)
},
serializers: {
// Serialize: Date -> seconds
date: (val: Date) => Math.floor(val.getTime() / 1000)
}
})spoofMethod?
optionalspoofMethod?:IQSpoofMethod
HTTP method to spoof via a _method field appended as the first entry of the resulting FormData when calling toFormData().
Enables frameworks such as Laravel, Symfony, and Rails to receive PUT, PATCH, DELETE, WebDAV, and other non-POST methods through a standard multipart/form-data POST request.
Cascading precedence (lowest → highest): QConfig.defaults.spoofMethod → @Quick({}, { spoofMethod }) → toFormData({ spoofMethod })
See
IQSpoofMethod for the full list of valid values
stripInternalIdentifiers?
optionalstripInternalIdentifiers?:boolean|string[]
Automatically excludes properties starting with internal prefixes (default: _, $) from population.
true: Strips properties starting with_or$(or global configured prefixes).false: Allows internal properties.string[]: Strips properties starting with these specific prefixes (overrides global).
Used to protect internal state from mass-assignment attacks.
trace?
optionaltrace?:object
Per-model structured trace configuration.
Overrides the global QConfig.configure({ defaults: { trace: { ... } } }) setting for this specific model class only.
events?
optionalevents?:IQTraceEvent[]
Filter which lifecycle events to trace for this model. When omitted, all events matching verbosity are traced.
sink?
optionalsink?: (entry) =>void
Custom sink for trace entries from this model only. When provided, entries are forwarded here instead of console.
Parameters
entry
IQTraceEntry
Returns
void
verbosity?
optionalverbosity?:IQTraceVerbosity
Minimum verbosity level to emit for this model. Overrides the global trace.verbosity.
Example
@Quick({ createdAt: Date }, {
trace: {
verbosity: 'verbose',
events: ['rule-fail', 'construction'],
}
})
class OrderModel extends QModel<IOrder> { ... }transformCase?
optionaltransformCase?:IQCaseOptions
Case transformation strategy for input (API -> Model) and output (Model -> API).
transformerOptions?
optionaltransformerOptions?: { [K in string | number | symbol]?: Record<string, unknown> }
Configuration options passed to transformers.
Allows configuring specific limits or behaviors for built-in transformers. e.g. maxBytes for ArrayBuffer, maxItems for TypedArray.
Example
@Quick({
video: ArrayBuffer
}, {
transformerOptions: {
video: { maxBytes: 5_000_000 } // Allow 5MB
}
})transformers?
optionaltransformers?: { [K in string | number | symbol]?: IQTransformerFn }
Custom transformers for specific properties.
Allows overriding the default deserialization logic for specific fields by providing a custom function that receives the raw value and returns the transformed value.
Example
@Quick({
status: String // Normal string
}, {
transformers: {
status: (val) => val.toUpperCase() // Custom transformation
}
})unknownPropertyPolicy?
optionalunknownPropertyPolicy?:"error"|"keep"|"strip"
Behavior when encountering properties in input data that are not defined in the model.
- keep (default): Preserves extra properties.
- strip: Silently removes extra properties.
- error: Throws an error.
validationTrigger?
optionalvalidationTrigger?:"manual"|"construction"
When to run integrity check.
- manual (default): Check must be triggered explicitly via
.$qCheckIntegrity(). - construction: Check runs automatically after population. Throws if it fails.