Valores por defecto (@QDefault)
El decorador @QDefault() declara un valor de fallback para un campo del modelo. El valor por defecto se aplica durante la construcción solo cuando el valor entrante es undefined o null — nunca reemplaza false, 0 ni ''.
Uso básico
import { Quick, QModel, QDefault } from 'quickmodel';
interface IOrder {
id: string;
status: string;
retries: number;
}
@Quick()
class OrderModel extends QModel<IOrder> {
declare id: string;
@QDefault('pending')
declare status: string;
@QDefault(0)
declare retries: number;
}
new OrderModel({ id: 'o1' }).status; // → 'pending'
new OrderModel({ id: 'o1', status: 'shipped' }).status; // → 'shipped'
new OrderModel({ id: 'o1', retries: 0 }).retries; // → 0 (no se reemplaza)Valores estáticos vs factorías
Para valores primitivos (string, number, boolean) — pasa el valor directamente:
@QDefault('active')
declare state: string;
@QDefault(100)
declare limit: number;Para tipos por referencia (arrays, objetos, Date) — usa siempre una función factoría para garantizar que cada instancia obtiene su propia copia:
@Quick()
class EventModel extends QModel<IEvent> {
@QDefault(() => [])
declare tags: string[]; // array propio por instancia
@QDefault(() => new Date())
declare createdAt: Date; // Date propio por instancia
@QDefault(() => ({ x: 0, y: 0 }))
declare position: IPoint; // objeto propio por instancia
}WARNING
Nunca pases un tipo por referencia como valor estático — todas las instancias compartirían el mismo objeto:
// ❌ Incorrecto — todas las instancias comparten el mismo array
@QDefault([])
declare tags: string[];
// ✅ Correcto — cada instancia obtiene su propio array
@QDefault(() => [])
declare tags: string[];Manejo de null y undefined
@QDefault se activa cuando el valor entrante es undefined o null:
const a = new OrderModel({ id: 'o1' });
a.status; // → 'pending' (undefined → se aplica el default)
const b = new OrderModel({ id: 'o1', status: null });
b.status; // → 'pending' (null → se aplica el default)
const c = new OrderModel({ id: 'o1', status: '' });
c.status; // → '' (cadena vacía → NO se reemplaza)Combinación con otros decoradores
@QDefault se compone con @QReadonly, @QSensitive y @QTransform:
@Quick()
class ApiKey extends QModel<IApiKey> {
@QReadonly()
@QDefault(() => crypto.randomUUID())
declare id: string; // ID inmutable, generado automáticamente si no se proporciona
@QSensitive()
@QDefault('—')
declare secret: string; // sensible + tiene un placeholder seguro por defecto
}Herencia
Las declaraciones de @QDefault se heredan — las clases hijas reciben automáticamente todos los defaults del padre:
@Quick()
class BaseEntity extends QModel<IBaseEntity> {
@QDefault(() => new Date())
declare createdAt: Date;
}
@Quick()
class UserModel extends BaseEntity {
declare name: string;
}
new UserModel({ name: 'Alice' }).createdAt; // → Date actualcopy() y patch()
Los defaults no se vuelven a aplicar en copy() ni en patch(). Solo se ejecutan en la construcción inicial con new Model(data):
const order = new OrderModel({ id: 'o1' });
order.status; // → 'pending'
const updated = order.$qCopy({ retries: 3 });
updated.status; // → 'pending' (nueva instancia copiando desde 'pending')Referencia de API
| Símbolo | Descripción |
|---|---|
@QDefault(valor) | Establece un default estático (primitivos) |
@QDefault(() => valor) | Establece un default con factoría (tipos por referencia) |
Ver también
@QReadonly— inmutabilidad del campo tras la construcción@QTransform— transformaciones post-deserialización@QSensitive— excluir campos sensibles de la serialización