Saltar al contenido principal

emptyKeys

Paquete: @tiendana/utils

Identifica qué propiedades de un objeto tienen valores vacíos (null, undefined, '', NaN, []) entre un conjunto de claves especificadas.

Características​

✅ Filtra propiedades vacías de un objeto
✅ Trabaja con lista específica de claves
✅ Usa hasValue internamente para validación
✅ Retorna array de strings (nombres de propiedades)
✅ Útil para validación de formularios
✅ Identificación rápida de campos faltantes

Firma​

function emptyKeys(obj: any, keys: string[]): string[]

Parámetros​

ParámetroTipoDescripciónRequerido
objanyObjeto a validar✅
keysstring[]Array de nombres de propiedades a verificar✅

Retorno​

Tipo: string[]

Array con los nombres de las propiedades que tienen valores vacíos.

Ejemplos de Uso​

Validación Básica​

import { emptyKeys } from '@tiendana/utils';

const user = {
name: 'Juan',
email: '',
phone: null,
age: 30
};

emptyKeys(user, ['name', 'email', 'phone']);
// ['email', 'phone']

Validación de Formulario​

interface RegistrationForm {
firstName: string;
lastName: string;
email: string;
phone: string;
terms: boolean;
}

function validateRegistration(form: RegistrationForm): string[] {
const requiredFields = ['firstName', 'lastName', 'email'];
return emptyKeys(form, requiredFields);
}

const formData = {
firstName: 'Juan',
lastName: '',
email: 'juan@example.com',
phone: '',
terms: false
};

const missing = validateRegistration(formData);
// ['lastName']

if (missing.length > 0) {
console.error(`Campos requeridos vacíos: ${missing.join(', ')}`);
}

Validación con Mensajes Personalizados​

const fieldLabels: Record<string, string> = {
firstName: 'Nombre',
lastName: 'Apellido',
email: 'Correo Electrónico',
phone: 'Teléfono'
};

function getValidationErrors(data: any, required: string[]): string[] {
const empty = emptyKeys(data, required);
return empty.map(key => `${fieldLabels[key]} es requerido`);
}

const errors = getValidationErrors(formData, ['firstName', 'lastName', 'email']);
// ['Apellido es requerido']

Validación de Múltiples Secciones​

interface CheckoutForm {
// Billing
billingName: string;
billingAddress: string;
billingCity: string;

// Shipping
shippingName: string;
shippingAddress: string;
shippingCity: string;

// Payment
cardNumber: string;
cardExpiry: string;
cardCvv: string;
}

function validateCheckout(form: CheckoutForm) {
const billingFields = ['billingName', 'billingAddress', 'billingCity'];
const shippingFields = ['shippingName', 'shippingAddress', 'shippingCity'];
const paymentFields = ['cardNumber', 'cardExpiry', 'cardCvv'];

return {
billing: emptyKeys(form, billingFields),
shipping: emptyKeys(form, shippingFields),
payment: emptyKeys(form, paymentFields)
};
}

const validation = validateCheckout(checkoutData);
// {
// billing: [],
// shipping: ['shippingCity'],
// payment: ['cardCvv']
// }

Validación Condicional​

function validateUserProfile(user: any, role: 'admin' | 'user'): string[] {
const baseFields = ['name', 'email'];
const adminFields = role === 'admin'
? [...baseFields, 'department', 'permissions']
: baseFields;

return emptyKeys(user, adminFields);
}

validateUserProfile(adminUser, 'admin');
// ['department'] - falta department para admin

validateUserProfile(regularUser, 'user');
// [] - user solo necesita name y email

Verificar Progreso de Formulario​

function getFormProgress(data: any, allFields: string[]): number {
const empty = emptyKeys(data, allFields);
const filled = allFields.length - empty.length;

return Math.round((filled / allFields.length) * 100);
}

const progress = getFormProgress(formData, [
'firstName', 'lastName', 'email', 'phone', 'address', 'city'
]);
// 67: solo lastName y phone existen y están vacíos; address y city no
// existen en formData, por lo que emptyKeys no los reporta y cuentan como completos

Validación de API Request​

interface CreateProductRequest {
name: string;
price: number;
category: string;
description: string;
sku: string;
}

function validateProductRequest(req: Partial<CreateProductRequest>): {
valid: boolean;
missing: string[];
} {
const requiredFields = ['name', 'price', 'category', 'sku'];
const missing = emptyKeys(req, requiredFields);

return {
valid: missing.length === 0,
missing
};
}

const validation = validateProductRequest({
name: 'Product Name',
price: 0, // 0 es válido (hasValue retorna true)
category: '',
sku: 'SKU-123'
});
// { valid: false, missing: ['category'] }

// validateProductRequest({ name: 'x' }) → { valid: true, missing: [] }: los campos ausentes no se reportan

Resaltar Campos Vacíos en UI​

interface FormField {
name: string;
label: string;
value: any;
error?: string;
}

function markEmptyFields(
fields: FormField[],
data: any
): FormField[] {
const fieldNames = fields.map(f => f.name);
const empty = emptyKeys(data, fieldNames);

return fields.map(field => ({
...field,
error: empty.includes(field.name)
? `${field.label} es requerido`
: undefined
}));
}

const formFields = [
{ name: 'name', label: 'Nombre', value: formData.name },
{ name: 'email', label: 'Email', value: formData.email }
];

const fieldsWithErrors = markEmptyFields(formFields, formData);
// Campos con error: 'email es requerido' si email está vacío

Validación antes de Enviar​

function canSubmitForm(data: any, requiredFields: string[]): boolean {
return emptyKeys(data, requiredFields).length === 0;
}

const submitButton = document.querySelector('#submit-btn');

if (canSubmitForm(formData, ['name', 'email', 'terms'])) {
submitButton.disabled = false;
} else {
submitButton.disabled = true;
}

Casos de Uso Comunes​

  • Validación de formularios: Identificar campos requeridos no completados
  • Progreso de formulario: Calcular porcentaje de completitud
  • Validación de API: Detectar campos presentes pero vacíos (los ausentes no se reportan)
  • UI highlighting: Marcar campos vacíos con estilos de error
  • Prevención de envío: Deshabilitar botón submit si faltan campos
  • Mensajes de error: Generar mensajes específicos por campo vacío
  • Validación condicional: Validar diferentes campos según contexto

Valores Considerados Vacíos​

La función usa hasValue internamente, por lo que considera vacíos:

  • null
  • undefined
  • '' (string vacío)
  • NaN
  • [] (array vacío)

NO considera vacíos:

  • 0 (número cero)
  • false (booleano)
  • {} (objeto vacío)
const data = {
count: 0, // ✅ No vacío
active: false, // ✅ No vacío
items: [], // ❌ Vacío (un array sin elementos)
config: {}, // ✅ No vacío
name: '', // ❌ Vacío
email: null, // ❌ Vacío
phone: undefined // ❌ Vacío
};

emptyKeys(data, ['count', 'active', 'items', 'config', 'name', 'email', 'phone']);
// ['items', 'name', 'email', 'phone']

Notas Técnicas​

  • Performance: O(n) donde n es el número de keys a verificar
  • Filter-based: Usa Array.filter() para identificar keys vacías
  • Type-agnostic: Acepta any para flexibilidad en validación
  • Dependencia: Requiere hasValue de @tiendana/utils
  • No modifica objeto: Solo lee propiedades, no las modifica
  • Keys no existentes: Solo se revisan las claves que existen en el objeto; una clave de keys que obj no tiene nunca se reporta

Diferencias con hasValue​

import { hasValue, emptyKeys } from '@tiendana/utils';

// hasValue: Valida UN valor
hasValue(user.email); // false

// emptyKeys: Valida MÚLTIPLES propiedades
emptyKeys(user, ['email', 'phone', 'name']); // ['email', 'phone']

Limitaciones​

Los objetos vacíos NO se consideran vacíos

{} pasa como valor presente, porque hasValue solo mira la longitud de los arrays:

const data = {
tags: [],
config: {}
};

emptyKeys(data, ['tags', 'config']);
// ['tags'] ← el array vacío se reporta, el objeto vacío no

// Si necesitas validar también objetos vacíos:
function isEmptyValue(value: any): boolean {
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
return Object.keys(value).length === 0;
}
return !hasValue(value);
}
Las keys inexistentes NO se reportan

La función itera las claves del objeto y las filtra contra keys. Si una clave de keys no existe en el objeto, no aparece en el resultado:

const user = { name: 'Juan', phone: '' };

emptyKeys(user, ['name', 'email', 'phone']);
// ['phone'] ← 'email' no existe en el objeto y se ignora

Para exigir campos obligatorios, inicializa todos los campos en el objeto (por ejemplo con null).

Ver También​

  • hasValue - Validar si un valor individual tiene contenido
  • getPath - Acceder a propiedades anidadas
  • deepMerge - Fusionar objetos