Volver al inicio

PropertyDescriptors para la validación de esquemas de TypeScript

Biblioteca de validación que usa PropertyDescriptors para selectores de errores seguros de tipos en lugar de rutas de strings. Soporta API fluida inmutable, introspección en tiempo de ejecución y extensiones. Compatibilidad total con Standard Schema v1 para el ecosistema.

Validación segura de tipos: PropertyDescriptors en lugar de strings
Advertisement 728x90

Descriptores de Propiedades para Validación de Esquemas: Manejo Seguro de Errores en TypeScript

Los desarrolladores suelen lidiar con la validación de objetos complejos y anidados en proyectos de JavaScript. Los enfoques tradicionales que usan rutas de cadenas para extraer errores generan fallos en tiempo de ejecución durante refactorizaciones. ¿La solución? Descriptores de propiedades: un árbol estructurado de descriptores que ofrece selectores con seguridad de tipos y autocompletado completo en el IDE.

La idea central es que cada esquema construye un árbol de nodos, donde cada descriptor conoce su ruta de propiedad, esquema vinculado, padre y métodos de acceso. Esto permite compilar selectores mediante lambdas en lugar de cadenas frágiles.

import { object, string, number, InferType } from '@cleverbrush/schema';

const OrderSchema = object({
    id: string(),
    customer: object({
        name: string().minLength(2),
        email: string().email(),
        address: object({
            city: string().required('La ciudad es obligatoria'),
            zip: number()
        })
    }),
    total: number().min(0)
});

const result = OrderSchema.validate({
    id: '123',
    customer: {
        name: 'A',
        email: 'not-an-email',
        address: {
            zip: -1
        }
    },
    total: -5
});

const nameErrors = result.getErrorsFor(t => t.customer.name);
const cityErrors = result.getErrorsFor(t => t.customer.address.city);

Renombra un campo y TypeScript lo detecta en tiempo de compilación. Tu IDE ofrece autocompletado completo.

Google AdInline article slot

API Fluida Inmutable y Constructores

Todas las llamadas a métodos de esquema devuelven nuevas instancias, evitando mutaciones. Esto facilita la composición y el reutilización.

La librería ofrece 14 tipos de constructores:

  • string() — minLength, maxLength, matches, email, url, uuid
  • number() — min, max, positive, negative, finite, multipleOf
  • boolean() — validación básica
  • date() — minDate, maxDate
  • object() — propiedades con nombre
  • array() — elementos tipados, no vacío
  • union() — uniones discriminadas
  • tuple() — longitud fija
  • record() — claves dinámicas
  • func() — tipado de funciones
  • any() — con hasType
  • null() — null
  • lazy() — esquemas recursivos
  • extern() — envoltorio de Standard Schema v1

Métodos comunes en el SchemaBuilder base:

Google AdInline article slot
  • .optional() — acepta undefined
  • .required('msg') — campo obligatorio
  • .nullable() — acepta null
  • .default(value) — valor por defecto
  • .catch(value) — valor de respaldo en error
  • .readonly() — Readonly<T>
  • .brand<'T'>() — tipos con marca
  • .describe('text') — preservación de JSDoc
  • .addValidator(fn) — lógica personalizada
  • .addPreprocessor(fn) — preprocesamiento
  • .introspect() — metadatos

Introspección de Esquemas en Tiempo de Ejecución

El método .introspect() devuelve una descripción completa del esquema: tipo, restricciones, flags, descripciones y extensiones. Todo disponible en tiempo de ejecución para herramientas e integraciones.

const Name = string().minLength(2).maxLength(100).describe('Nombre de usuario').optional();

const info = Name.introspect();
// info.type === 'string'
// info.minLength === 2
// info.description === 'Nombre de usuario'

La introspección se expande completamente para cada constructor. Ideal para conversión a JSON Schema, generación de formularios o renderizadores personalizados.

Sistema de Extensiones Tipadas

Las extensiones son complementos composables e introspeccionables al núcleo. Ejemplo para colores HEX y puertos:

Google AdInline article slot
const hexColorExt = defineExtension({
    string: {
        hexColor(this: StringSchemaBuilder) {
            return this.addValidator((v) => {
                const valid = /^#[0-9a-f]{6}$/i.test(v as string);
                return {
                    valid,
                    errors: valid ? [] : [{ message: 'Debe ser un color HEX válido' }]
                };
            });
        }
    }
});

const s = withExtensions(hexColorExt, portExt);
const colorSchema = s.string().hexColor();

Las extensiones aparecen en .introspect().extensions. Las integradas incluyen email, url, uuid, positive, nonempty.

Compatibilidad con Standard Schema v1

Los esquemas implementan Standard Schema v1 para una integración fluida con tRPC, TanStack Form, React Hook Form, Hono. extern() envuelve Zod/Valibot en constructores.

const UserSchema = object({
    name: string().minLength(2),
    address: extern(zodAddress)
});

Los Descriptores de Propiedades ofrecen acceso seguro a errores incluso en esquemas mixtos.

Lecciones Clave

  • Selectores con seguridad de tipos mediante Descriptores de Propiedades eliminan rutas de cadenas y errores en runtime.
  • API fluida inmutable simplifica la composición sin efectos secundarios.
  • Introspección en runtime extrae metadatos para cualquier herramienta.
  • Extensiones — complementos tipados y composables al núcleo.
  • Standard Schema v1 garantiza compatibilidad con el ecosistema.

— Editorial Team

Advertisement 728x90

Leer después