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 de string).
  • 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.