deepkit/type para TypeScript: guía completa con ejemplos
En el mundo de TypeScript existe un problema fundamental: los tipos solo existen en tiempo de compilación. Después de la transpilación a JavaScript, toda la información sobre los tipos desaparece. Esto hace imposible la validación en tiempo de ejecución, la serialización dinámica o la construcción de sistemas complejos que dependan de metadatos de tipos. La librería deepkit/type resuelve este problema de forma radical: traslada el sistema de tipos de TypeScript al runtime, permitiendo trabajar con los tipos como si fueran datos.
El valor principal de deepkit/type es que no requiere escribir esquemas duplicados (como en Zod o Yup). Tú describes los tipos una sola vez —en TypeScript puro— y la librería los extrae automáticamente en tiempo de ejecución. Esto permite realizar validación de datos, serialización/deserialización, reflexión (obtener información sobre propiedades, genéricos, decoradores) e incluso generar código basado en tipos. deepkit/type no es solo un validador, sino un framework completo para metaprogramación.
La librería es ideal para proyectos donde la tipificación estricta es importante en todos los niveles: servidores API (validación de solicitudes entrantes), bases de datos (mapeo de tipos a SQL), archivos de configuración, sistemas RPC y herramientas de generación de código. Gracias a su integración con deepkit/framework, también se usa para crear aplicaciones de servidor de alto rendimiento con validación y serialización automáticas.
Instalación
deepkit/type es un paquete npm para TypeScript. La instalación se realiza con el comando estándar:
npm install @deepkit/type reflect-metadata
También necesitarás configurar tu tsconfig.json para soportar decoradores y emitir metadatos:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": true,
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist"
}
}
Si usas ts-node para ejecutar, asegúrate de que cargue reflect-metadata primero. Agrega al inicio de tu archivo de entrada:
import 'reflect-metadata';
Inicio rápido
Un ejemplo mínimo demuestra cómo declarar un tipo y obtener su representación en runtime:
import 'reflect-metadata';
import { typeOf, ReflectionClass } from '@deepkit/type';
// Declaramos una interfaz
interface User {
id: number;
name: string;
email?: string;
}
// Obtenemos el tipo en runtime
const userType = typeOf();
console.log(userType); // ReflectionClass
// Verificamos las propiedades
const reflection = ReflectionClass.from(userType);
console.log(reflection.getProperty('name').type); // ReflectionProperty
console.log(reflection.getProperty('id').type.kind); // 'number'
Este código mostrará información sobre el tipo User en la consola. Nota: no escribimos ningún esquema —solo una interfaz TypeScript pura.
Métodos y funciones principales
A continuación se presentan las capacidades clave de deepkit/type. Para cada método se indica la firma, una breve descripción y un ejemplo funcional.
1. typeOf
Firma: typeOf<T>(): ReflectionClass
Qué hace: Extrae la representación en runtime del tipo T. Devuelve un objeto ReflectionClass que contiene información completa sobre la estructura del tipo: propiedades, sus tipos, modificadores (optional, readonly), genéricos y decoradores.
import { typeOf } from '@deepkit/type';
interface Product {
id: number;
title: string;
price: number;
}
const productType = typeOf();
console.log(productType.getProperty('title').type.kind); // 'string'
console.log(productType.getProperty('price').type.kind); // 'number'
2. is
Firma: is<T>(value: unknown): value is T
Qué hace: Valida si un valor desconocido coincide con el tipo T en tiempo de ejecución. Actúa como un guardia de tipo (type guard) de TypeScript, devolviendo true si el valor es válido y false en caso contrario.
import { is } from '@deepkit/type';
interface User {
id: number;
name: string;
email?: string;
}
const data: unknown = { id: 1, name: 'Ana' };
if (is(data)) {
console.log(data.name); // TypeScript sabe que 'data' es User aquí
} else {
console.log('Datos inválidos');
}
3. cast
Firma: cast<T>(value: unknown): T
Qué hace: Convierte (hace cast) de un valor desconocido al tipo T, lanzando una excepción si la conversión falla. Útil para deserializar datos de APIs o archivos JSON de forma segura.
import { cast } from '@deepkit/type';
interface Config {
port: number;
host: string;
debug: boolean;
}
const rawData = JSON.parse('{"port": 3000, "host": "localhost", "debug": true}');
const config = cast(rawData);
console.log(config.port); // 3000
4. serialize
Firma: serialize<T>(value: T): any
Qué hace: Serializa un objeto tipado a un formato plano (JSON-compatible). Respeta decoradores y reglas de transformación definidas en el tipo.
import { serialize } from '@deepkit/type';
class User {
id: number = 0;
name: string = '';
@hidden // decorador para ocultar este campo
password: string = '';
}
const user = new User();
user.id = 1;
user.name = 'Carlos';
user.password = 'secreto';
const serialized = serialize(user);
console.log(serialized); // { id: 1, name: 'Carlos' } - password oculto
5. deserialize
Firma: deserialize<T>(value: any): T
Qué hace: Deserializa un objeto plano (por ejemplo, de JSON) a una instancia tipada de la clase T. Aplica validación y transformaciones automáticamente.
import { deserialize } from '@deepkit/type';
class Product {
id: number = 0;
title: string = '';
price: number = 0;
}
const raw = { id: 1, title: 'Laptop', price: 999.99 };
const product = deserialize(raw);
console.log(product instanceof Product); // true
console.log(product.title); // 'Laptop'
6. ReflectionClass
Firma: ReflectionClass.from(type: ReflectionClass): ReflectionClass
Qué hace: Proporciona una API completa para inspeccionar tipos en runtime. Permite obtener propiedades, métodos, decoradores, genéricos y más. Es la base para la metaprogramación con deepkit/type.
import { typeOf, ReflectionClass } from '@deepkit/type';
interface Task {
id: number;
title: string;
completed: boolean;
}
const taskType = typeOf();
const reflection = ReflectionClass.from(taskType);
// Listar todas las propiedades
for (const prop of reflection.getProperties()) {
console.log(`${prop.name}: ${prop.type.kind}`);
}
// id: number
// title: string
// completed: boolean
Conclusión
deepkit/type transforma la forma en que trabajamos con tipos en TypeScript, llevando la seguridad de tipos al runtime sin necesidad de esquemas duplicados. Con métodos como typeOf, is, cast, serialize y deserialize, puedes validar, transformar e inspeccionar datos de manera eficiente. Es una herramienta imprescindible para proyectos que requieren tipificación estricta en todos los niveles, desde APIs hasta bases de datos.
¿Listo para probarlo? Instala deepkit/type hoy y descubre el poder de los tipos en runtime con TypeScript.
También en la biblioteca
Aprendizaje automático en Rust: revisión de bibliotecas para Data Science
Puppeteer para JavaScript (Node.js): guía completa con ejemplos