A nova sintaxe de parâmetro de tipo const do TypeScript permite que uma função mantenha os tipos literais intactos sem forçar quem a chama a espalhar as const por toda parte, eliminando a fonte mais comum de bugs de alargamento de tipo (type-widening).
O problema de alargamento que assombra o código genérico
Quando uma função genérica recebe um objeto literal, o compilador alarga qualquer propriedade literal para o seu tipo primitivo mais amplo.
function call<T>(arg: T) {}
call({ method: "GET" }) // T is inferred as { method: string }
O literal "GET" é reduzido a string. O código subsequente que depende do valor exato — como uniões discriminadas (discriminated unions) ou extração de template-literals — quebra porque o tipo não carrega mais o literal preciso. Os desenvolvedores há muito tempo contornam isso escrevendo { method: "GET" } as const no local da chamada, o que diz ao compilador para manter o literal, mas essa correção fica nas mãos de quem chama, não na definição da função.
Parâmetros de tipo const: uma correção ao nível da assinatura
O novo modificador const em um parâmetro de tipo diz ao compilador para inferir o tipo mais estreito possível para aquele argumento genérico. Declarar uma função como function foo<const T>(arg: T) faz com que T se comporte automaticamente como se quem a chamasse tivesse escrito as const.
- Literais de string, number e boolean permanecem com seus valores exatos (
"GET"em vez destring). - Arrays tornam-se tuplas somente leitura (readonly) com cada elemento tipado precisamente.
- Objetos tornam-se estruturas profundamente somente leitura, preservando os tipos literais em todos os níveis de aninhamento.
Como a restrição reside na assinatura da função, todos os chamadores se beneficiam automaticamente; esquecer um cast não é mais um caminho para a insegurança de tipos (unsoundness).
Por que isso supera o hack clássico do as const
O as const é uma solução do lado do chamador. Ele exige que cada consumidor de uma função genérica se lembre de adicionar a asserção. Se perder uma única chamada, a segurança de tipos evapora. O parâmetro de tipo const move a responsabilidade para o próprio design da API: a função declara "Eu preciso da forma mais estreita de qualquer coisa que você passar", e o compilador a impõe.
Essa mudança é mais importante para bibliotecas e utilitários que expõem builders genéricos, fábricas de configuração ou qualquer API onde o valor literal de um campo dite a lógica de tipos. O autor da biblioteca pode garantir a inferência correta sem precisar policiar o código subsequente.
Cenários do mundo real que se beneficiam
- Builders de configuração – nomes de ambiente (
"dev" | "prod") permanecem literais, permitindo verificações de uniões discriminadas sem casts extras. - Definições de rotas de API – strings de caminho permanecem exatas, permitindo que tipos de template-literal extraiam parâmetros (
"/users/:id"→\/users/${string}``). - Helpers de máquinas de estado – identificadores de estado permanecem literais fixos através de encadeamento de métodos, evitando incompatibilidades de estado acidentais.
Em cada caso, o parâmetro const elimina um boilerplate recorrente de as const e reduz a chance de bugs sutis passarem despercebidos.
Combinando com o operador satisfies
O operador satisfies valida que um valor está em conformidade com um tipo estrutural enquanto preserva sua informação literal original. Usar ambos juntos oferece o melhor dos dois mundos: parâmetros const fornecem inferência estreita, e o satisfies garante que o valor atenda à forma exigida.
function makeConfig<const C>(cfg: C) {
// cfg is inferred with exact literals
}
const cfg = {
env: "staging",
ports: [8080, 8443],
} satisfies { env: string; ports: number[] };
makeConfig(cfg); // works, literals stay intact
Quando manter o as const
O parâmetro const brilha quando você controla a assinatura da função. Se você estiver lidando com funções de terceiros que não possuem o modificador, ou precisar de uma preservação de literal pontual para uma variável local, o as const continua sendo a ferramenta certa. Ele ainda serve como a maneira padrão de congelar um valor sem alterar a API chamada.
O que observar a seguir
O recurso ainda é recente, então as ferramentas e os padrões da comunidade estão evoluindo. Espere atualizações no suporte de IDEs que tragam a nova sintaxe para o preenchimento automático e sugestões de correção rápida. Fique de olho nos mantenedores de bibliotecas: muitos começarão a migrar genéricos públicos para parâmetros const, o que pode introduzir mudanças que quebram o código (breaking changes) que anteriormente dependia de casts explícitos de as const.
Resumo: Ao incorporar a preservação de literais diretamente nos parâmetros de tipo de uma função, os parâmetros de tipo const do TypeScript removem uma fonte comum de erros de alargamento e transferem a segurança do chamador de volta para o designer da API. Use-os para qualquer ponto de entrada genérico de sua autoria; reserve o as const para valores locais ou APIs externas.
