Skip to content

Alias de Claves con @QAlias ​

@QAlias mapea una propiedad del modelo a un nombre de clave externo que se usa tanto en la entrada (create(), new, fromJSON()) como en la salida (serialize(), toJSON()). Esto facilita trabajar con APIs en snake_case manteniendo camelCase en el código del modelo.

Ejemplo Básico ​

typescript
import { Quick, QModel, QAlias } from 'quickmodel';

interface IUsuario {
	firstName: string;
	lastName: string;
	emailAddress: string;
}

type IUsuarioAliasMap = {
	firstName: 'first_name';
	lastName: 'last_name';
	emailAddress: 'email_address';
};

@Quick()
class UsuarioModel extends QModel<IUsuario, IUsuarioAliasMap> {
	@QAlias('first_name')
	declare firstName: string;

	@QAlias('last_name')
	declare lastName: string;

	@QAlias('email_address')
	declare emailAddress: string;
}

Entrada: create() con payload en snake_case ​

typescript
// Funciona con claves alias (p. ej. desde una API REST) — tipado completo, sin `as any`:
const usuario = UsuarioModel.create({
	first_name: 'Alice',
	last_name: 'Smith',
	email_address: 'alice@ejemplo.com',
});

console.log(usuario.firstName); // 'Alice'             ✅ camelCase dentro del modelo
console.log(usuario.emailAddress); // 'alice@ejemplo.com'

TIP

Pasar las claves camelCase originales (firstName, etc.) también funciona como fallback. Cuando están ambas — la clave alias y la clave de propiedad — en el payload, la alias tiene prioridad.

Salida: serialize() emite claves alias ​

typescript
const salida = usuario.$qSerialize();
// {
//   first_name: 'Alice',
//   last_name: 'Smith',
//   email_address: 'alice@ejemplo.com'
// }

const json = usuario.toJSON();
// '{"first_name":"Alice","last_name":"Smith","email_address":"alice@ejemplo.com"}'

Los campos sin @QAlias conservan su nombre de propiedad original en la salida.

Roundtrip Completo ​

Dado que tanto la entrada como la salida usan las claves alias, el resultado serializado puede pasarse directamente de vuelta a create():

typescript
const serializado = usuario.$qSerialize();
const restaurado = UsuarioModel.create(serializado);

restaurado.firstName === 'Alice'; // ✅
restaurado.emailAddress === 'alice@ejemplo.com'; // ✅

fromJSON() también soporta el roundtrip:

typescript
const json = usuario.toJSON();
const restaurado = UsuarioModel.fromJSON(json);
restaurado.firstName === 'Alice'; // ✅

Campos Mixtos ​

Solo las propiedades decoradas con @QAlias son remapeadas. Los demás campos conservan sus claves originales.

typescript
type IPerfilAliasMap = { nombreCompleto: 'nombre_completo' };

@Quick({ fechaNacimiento: Date })
class PerfilModel extends QModel<IPerfil, IPerfilAliasMap> {
	@QAlias('nombre_completo')
	declare nombreCompleto: string;

	declare fechaNacimiento: Date; // sin alias
}

const p = PerfilModel.create({
	nombre_completo: 'Jane Doe',
	fechaNacimiento: '1990-01-01',
});
p.nombreCompleto; // 'Jane Doe'  ✅
p.fechaNacimiento; // objeto Date ✅

p.$qSerialize();
// { nombre_completo: 'Jane Doe', fechaNacimiento: '1990-01-01T00:00:00.000Z' }

Herencia ​

Las subclases heredan los @QAlias del padre. Los alias adicionales se pueden declarar en la subclase.

typescript
@Quick()
class AdminModel extends UsuarioModel {
	@QAlias('numero_telefono')
	declare numeroTelefono: string;
}

const admin = AdminModel.create({
	first_name: 'Dan',
	last_name: 'Lee',
	email_address: 'dan@ejemplo.com',
	numero_telefono: '555-1234',
});

admin.firstName; // 'Dan'
admin.numeroTelefono; // '555-1234'
admin.$qSerialize(); // { first_name: 'Dan', ..., numero_telefono: '555-1234' }

Referencia de API ​

@QAlias(alias: string) ​

ParámetroTipoDescripción
aliasstringNombre de la clave externa (p. ej. 'first_name', 'user_id')

Comportamiento:

  • Remapping de entrada: si la clave alias está presente en el payload al crear, se renombra al nombre de propiedad antes de la deserialización. La clave camelCase sigue aceptándose como fallback.
  • Remapping de salida: serialize() y toJSON() emiten alias en lugar del nombre de propiedad.
  • Herencia: las subclases heredan los alias mediante recorrido de la cadena prototipo.

Casos de Uso Comunes ​

EscenarioEjemplo
API REST con campos en snake_case@QAlias('created_at') en createdAt
Mapeo de modelos externos@QAlias('user_id') en userId
Nombres de columnas de DB@QAlias('phone_number') en phoneNumber
Nombres de campo legacy@QAlias('e_mail') en email

Rendimiento ​

⚡ Comparativa de rendimiento

Pasa el ratón sobre las barras para ver detalles

2k instanciaciones — payload API en snake_case → modelo camelCase. Plain JS: el más rápido pero requiere mapper hardcoded que se rompe con cada cambio de schema. class-transformer: copia a instancia de clase pero mantiene las claves snake_case originales sin configuración @Expose+@Transform. QuickModel @QAlias: renombrado sin boilerplate al instanciar, compatible con coerción de tipos y validación.

QuickModel
250k ops/s
class-transformer
83k ops/s
Plain JS
21.8M ops/s
›› mucho más rápido (ver nota ↑)
← más lento       más rápido →