deepkit/type para TypeScript: guia completo com exemplos
No mundo do TypeScript, existe um problema fundamental: os tipos existem apenas em tempo de compilação. Após a transpilação para JavaScript, toda a informação sobre os tipos desaparece. Isso torna impossível a validação em runtime, a serialização dinâmica ou a construção de sistemas complexos que dependem de metadados de tipos. A biblioteca deepkit/type resolve esse problema de forma radical — ela transporta o sistema de tipos do TypeScript para o runtime, permitindo que você trabalhe com tipos como se fossem dados.
O principal valor do deepkit/type é que ele não exige a escrita de esquemas duplicados (como no Zod ou Yup). Você descreve os tipos uma vez — em TypeScript puro — e a biblioteca os extrai automaticamente para o runtime. Isso possibilita realizar validação de dados, serialização/desserialização, reflexão (obter informações sobre propriedades, genéricos, decoradores) e até gerar código com base nos tipos. deepkit/type não é apenas um validador, mas um framework completo para metaprogramação.
A biblioteca é ideal para projetos onde a tipagem estrita é importante em todos os níveis: servidores de API (validação de requisições de entrada), bancos de dados (mapeamento de tipos para SQL), arquivos de configuração, sistemas RPC e ferramentas de geração de código. Graças à integração com o deepkit/framework, ela também é usada para criar aplicações server-side de alta performance com validação e serialização automáticas.
Instalação
deepkit/type é um pacote npm para TypeScript. A instalação é feita com o comando padrão:
npm install @deepkit/type reflect-metadata
Você também precisará configurar o tsconfig.json para suportar decoradores e emissão de metadados:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": true,
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist"
}
}
Se você usa ts-node para executar, certifique-se de que ele carregue o reflect-metadata primeiro. Adicione ao início do seu arquivo de entrada:
import 'reflect-metadata';
Início rápido
Um exemplo mínimo demonstra como declarar um tipo e obter sua representação em runtime:
import 'reflect-metadata';
import { typeOf, ReflectionClass } from '@deepkit/type';
// Declara uma interface
interface User {
id: number;
name: string;
email?: string;
}
// Obtém o tipo em runtime
const userType = typeOf();
console.log(userType); // ReflectionClass
// Verifica as propriedades
const reflection = ReflectionClass.from(userType);
console.log(reflection.getProperty('name').type); // ReflectionProperty
console.log(reflection.getProperty('id').type.kind); // 'number'
Este código exibirá informações sobre o tipo User no console. Observe: não escrevemos nenhum esquema — apenas uma interface TypeScript pura.
Métodos e funções principais
Abaixo estão os principais recursos do deepkit/type. Para cada método, são fornecidos a assinatura, uma breve descrição e um exemplo funcional.
1. typeOf
Assinatura: typeOf<T>(): ReflectionClass
O que faz: Extrai a representação em runtime do tipo T. Retorna um objeto ReflectionClass contendo informações completas sobre a estrutura do tipo: propriedades, seus tipos, modificadores (optional, readonly), genéricos e 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
Assinatura: is<T>(value: unknown): value is T
O que faz: Verifica se um valor corresponde ao tipo T em runtime. Funciona como um type guard do TypeScript, permitindo validação de dados de forma segura e eficiente.
import { is } from '@deepkit/type';
interface User {
id: number;
name: string;
}
const data = { id: 1, name: 'João' };
if (is(data)) {
console.log('Dados válidos!');
} else {
console.log('Dados inválidos.');
}
3. cast
Assinatura: cast<T>(value: unknown): T
O que faz: Converte um valor para o tipo T, realizando transformações automáticas (como string para número) e validação. Lança um erro se a conversão for impossível.
import { cast } from '@deepkit/type';
interface Product {
id: number;
price: number;
}
const rawData = { id: '123', price: '49.99' };
const product = cast(rawData);
console.log(product.id); // 123 (number)
console.log(product.price); // 49.99 (number)
4. serialize
Assinatura: serialize<T>(value: T): unknown
O que faz: Serializa um objeto para um formato JSON puro, removendo propriedades opcionais não definidas e convertendo tipos complexos (como Date) para strings.
import { serialize } from '@deepkit/type';
interface Event {
id: number;
date: Date;
description?: string;
}
const event = new Event();
event.id = 1;
event.date = new Date('2024-01-01');
const serialized = serialize(event);
console.log(serialized); // { id: 1, date: '2024-01-01T00:00:00.000Z' }
5. deserialize
Assinatura: deserialize<T>(value: unknown): T
O que faz: Desserializa um objeto JSON puro de volta para o tipo T, restaurando tipos complexos como Date, Map ou classes personalizadas.
import { deserialize } from '@deepkit/type';
interface Event {
id: number;
date: Date;
}
const jsonData = { id: 1, date: '2024-01-01T00:00:00.000Z' };
const event = deserialize(jsonData);
console.log(event.date instanceof Date); // true
6. ReflectionClass
Assinatura: ReflectionClass.from(type: ReflectionClass): ReflectionClass
O que faz: Fornece uma API completa para inspecionar tipos em runtime. Permite acessar propriedades, métodos, decoradores e até mesmo genéricos de forma programática.
import { typeOf, ReflectionClass } from '@deepkit/type';
interface Config {
host: string;
port: number;
debug?: boolean;
}
const configType = typeOf();
const reflection = ReflectionClass.from(configType);
console.log(reflection.getProperty('host').type.kind); // 'string'
console.log(reflection.getProperty('port').isOptional()); // false
console.log(reflection.getProperty('debug').isOptional()); // true
Conclusão
deepkit/type é uma ferramenta poderosa que leva a tipagem do TypeScript para o próximo nível. Com ela, você elimina a necessidade de esquemas duplicados, reduz erros em runtime e ganha produtividade ao trabalhar com validação, serialização e reflexão de forma nativa. Se você busca uma solução robusta para metaprogramação em TypeScript, deepkit/type é a escolha certa.
Experimente hoje mesmo e veja como seus projetos podem se beneficiar de tipos em runtime!