TypeScript 5.x: as features que você deveria usar agora
1. Decorators nativos: o padrão que finalmente chegou
O TypeScript 5.0 trouxe os decorators nativos como uma feature estável, alinhada com a proposta do ECMAScript. Diferente dos decorators experimentais (experimentalDecorators), a nova implementação não requer flags de compilação e segue o padrão ES.
// Antes (experimental)
function log(target: any, key: string) {
console.log(`Chamando ${key}`);
}
// Agora (nativo - TypeScript 5.x)
function log(_target: any, context: ClassMethodDecoratorContext) {
const methodName = String(context.name);
return function(this: any, ...args: any[]) {
console.log(`Chamando ${methodName}`);
return this.method.apply(this, args);
};
}
class Servico {
@log
processar(dados: string) {
return `Processado: ${dados}`;
}
}
Para migrar, remova experimentalDecorators do tsconfig.json e atualize a assinatura dos decorators. Casos de uso incluem injeção de dependência, logging e validação.
2. Modificadores de acesso em construtores: parameter properties
Com parameter properties, você pode declarar e inicializar propriedades diretamente no construtor, reduzindo boilerplate significativamente.
// Abordagem tradicional
class Usuario {
public nome: string;
private email: string;
constructor(nome: string, email: string) {
this.nome = nome;
this.email = email;
}
}
// Com parameter properties (TypeScript 5.x)
class Usuario {
constructor(
public nome: string,
private email: string
) {}
}
Combinado com decorators, você pode adicionar validação automática:
function validarEmail(_target: any, context: ParameterDecoratorContext) {
// Implementação de validação
}
class Cadastro {
constructor(
public nome: string,
@validarEmail public email: string
) {}
}
3. const type parameters: inferência literal sem surpresas
O modificador const em type parameters preserva tipos literais em funções genéricas, evitando que arrays e objetos sejam ampliados para tipos mais genéricos.
// Sem const - perde informações literais
function criarRota<T extends string[]>(paths: T): T {
return paths;
}
const rota1 = criarRota(['/home', '/about']); // tipo: string[]
// Com const - preserva literais
function criarRota<const T extends string[]>(paths: T): T {
return paths;
}
const rota2 = criarRota(['/home', '/about']); // tipo: ['/home', '/about']
Isso é útil para funções de roteamento e configuração tipada:
function configurar<const T extends Record<string, string>>(config: T): T {
return config;
}
const config = configurar({ api: 'v1', timeout: '5000' });
// tipo: { api: 'v1'; timeout: '5000' } - não string genérico
4. satisfies operator: validação sem perda de tipo
O operador satisfies valida se um valor satisfaz um tipo, mas mantém o tipo literal inferido, não o substituindo pelo tipo de validação.
type CoresValidas = 'red' | 'blue' | 'green';
// Anotação explícita perde o literal
const cor1: CoresValidas = 'red'; // tipo: CoresValidas
// satisfies mantém o literal
const cor2 = 'red' satisfies CoresValidas; // tipo: 'red'
// Exemplo prático: objeto de configuração
type Config = Record<string, string | number>;
const config = {
url: 'https://api.example.com',
timeout: 5000,
retries: 3
} satisfies Config;
// config.url ainda é string literal, não string genérico
5. Melhorias em enum: união de tipos e strings
Enums tradicionais podem ser substituídos por alternativas mais modernas que oferecem melhor inferência de tipos.
// Enum tradicional
enum Status {
Ativo = 'ativo',
Inativo = 'inativo'
}
// Alternativa moderna com const enum
const enum Status {
Ativo = 'ativo',
Inativo = 'inativo'
}
// Alternativa com union types e as const
const Status = {
Ativo: 'ativo',
Inativo: 'inativo'
} as const;
type Status = typeof Status[keyof typeof Status];
// equivalente a: 'ativo' | 'inativo'
Use enum tradicional quando precisar de runtime checks ou compatibilidade com código legado. Para novos projetos, prefira as const com union types.
6. using declarations e disposição de recursos
O TypeScript 5.2 introduziu suporte a using declarations, que gerenciam automaticamente o ciclo de vida de recursos através de Symbol.dispose e Symbol.asyncDispose.
class ConexaoBanco {
[Symbol.dispose]() {
console.log('Fechando conexão...');
// Lógica de fechamento
}
query(sql: string) {
return `Resultado de: ${sql}`;
}
}
function processarDados() {
using db = new ConexaoBanco();
const resultado = db.query('SELECT * FROM usuarios');
// Conexão é fechada automaticamente ao sair do escopo
return resultado;
}
Para operações assíncronas:
class AsyncResource {
async [Symbol.asyncDispose]() {
await this.cleanup();
}
private async cleanup() {
// Limpeza assíncrona
}
}
async function usarRecurso() {
await using recurso = new AsyncResource();
// Recurso é liberado automaticamente
}
7. Isolated declarations e modo verbatimModuleSyntax
isolatedDeclarations permite gerar arquivos .d.ts sem análise cruzada entre arquivos, melhorando o tempo de compilação em projetos grandes.
// tsconfig.json
{
"compilerOptions": {
"isolatedDeclarations": true,
"verbatimModuleSyntax": true
}
}
verbatimModuleSyntax controla como as importações são processadas, garantindo que tipos sejam importados como import type e valores como import, melhorando a compatibilidade com bundlers.
8. Type-only imports/exports: performance e clareza
A sintaxe import type e export type permite eliminar código morto durante o tree-shaking, melhorando o bundle final.
// Antes
import { Usuario, funcaoUtil } from './modulo';
// Ambos são incluídos no bundle, mesmo que Usuario seja apenas tipo
// Depois (TypeScript 5.x)
import type { Usuario } from './modulo';
import { funcaoUtil } from './modulo';
// Usuario é removido durante a compilação
Boas práticas para migração:
// modulo.ts
export type Usuario = { nome: string };
export function funcaoUtil() { return 'util'; }
// Re-export type
export type { Usuario } from './modulo';
export { funcaoUtil } from './modulo';
Essas features do TypeScript 5.x oferecem melhorias significativas em produtividade, segurança de tipos e performance. Adotá-las progressivamente em projetos existentes ou desde o início em novos projetos resulta em código mais limpo, seguro e eficiente.
Referências
- TypeScript 5.0 Release Notes — Documentação oficial da Microsoft sobre as novidades do TypeScript 5.0, incluindo decorators nativos e const type parameters
- TypeScript 5.2 Release Notes — Anúncio oficial do TypeScript 5.2 com detalhes sobre
usingdeclarations e disposição de recursos - TypeScript Handbook: Decorators — Guia completo sobre decorators no TypeScript, incluindo a nova implementação padrão ES
- TypeScript Handbook: The satisfies Operator — Documentação oficial sobre o operador
satisfiese suas aplicações - TypeScript Deep Dive: Enums vs Union Types — Análise detalhada das diferenças entre enums tradicionais e union types modernos
- TypeScript Performance: Type-only Imports — Guia oficial sobre como usar
import typeeexport typepara melhor performance - MDN Web Docs: Symbol.dispose — Documentação do MDN sobre o protocolo de disposição de recursos em JavaScript/TypeScript