Menu

Strict mode em TypeScript: o que strict: true ativa

strict: true no tsconfig.json ativa uma família de verificações de tipos: noImplicitAny, strictNullChecks, strictPropertyInitialization e mais cinco. Veja o que cada uma pega, como ativar o strict mode em um projeto existente e as flags úteis que o strict não inclui.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Strict mode é a opção "strict": true do tsconfig.json. É um único interruptor para oito flags de verificação de tipos que pegam any implícito, null e undefined não verificados, atribuições inseguras de funções e campos de classe não inicializados. No TypeScript 7, strict vem ativado por padrão. Assim é um código que passa por ele:

A saída é no user, SyntaxError e 42. Remova o : number, o ?. ou a verificação com instanceof e o arquivo deixa de compilar.

Como ativar

{
    "compilerOptions": {
        "strict": true
    }
}

As flags individuais têm prioridade sobre strict, nos dois sentidos. "strict": true, "strictNullChecks": false mantém tudo, exceto a verificação de null; "strict": false, "noImplicitAny": true ativa só essa. strict também inclui automaticamente as verificações adicionadas em versões futuras, já que novas flags da família strict entram no grupo.

O strict do TypeScript não tem nada a ver com a diretiva "use strict" do JavaScript, que é um modo de execução. O TypeScript 7 sempre gera "use strict" onde é necessário, e definir alwaysStrict: false é o erro TS5108 (a opção foi removida).

O que cada flag pega

FlagO que ela apontaErro
noImplicitAnyum parâmetro ou variável cujo tipo seria any sem avisoTS7006 Parameter 'x' implicitly has an 'any' type.
strictNullChecksusar um valor que pode ser null ou undefinedTS18048 'u' is possibly 'undefined'.
strictFunctionTypesatribuir uma função cujo tipo de parâmetro é mais estreito que o exigidoTS2322
strictBindCallApplyargumentos errados para .call, .bind e .applyTS2345
strictPropertyInitializationum campo de classe que nunca recebe valorTS2564 Property 'name' has no initializer and is not definitely assigned in the constructor.
noImplicitThisthis com tipo any implícito, como em uma function aninhadaTS2683
useUnknownInCatchVariablesusar a variável do catch antes de estreitá-la (ela é unknown)TS18046 'err' is of type 'unknown'.
strictBuiltinIteratorReturntratar it.next().value de um iterador nativo como sempre definidoTS2322

As duas que mais mudam o código são noImplicitAny e strictNullChecks. Este bloco quebra as duas de propósito:

Ele imprime index.ts(2,17): error TS7006: Parameter 'x' implicitly has an 'any' type. e index.ts(11,13): error TS18048: 'user' is possibly 'undefined'. Sem strict, isso compila e depois quebra em tempo de execução com TypeError: Cannot read properties of undefined (reading 'name'). Com strict, a quebra vira um erro de compilação. As correções são o primeiro bloco desta página.

strictFunctionTypes: por que existe

Uma função que só trata strings não pode ser usada onde números podem chegar. A verificação abaixo está silenciada com @ts-expect-error para que você possa rodar e ver o que o erro evita:

Sem o comentário, a atribuição é o erro TS2322, Type '(s: string) => void' is not assignable to type 'Handler'., seguido de Types of parameters 's' and 'value' are incompatible. Resta uma exceção, de propósito: parâmetros de métodos declarados com a sintaxe de método (handle(value: string | number): void dentro de uma interface) ainda são verificados da forma mais frouxa, então shout poderia ser atribuída a um método assim sem erro.

strictPropertyInitialization

Todo campo de classe precisa receber um valor na declaração ou no construtor. Três formas de atender a isso:

Saída:

Account {
  owner: 'Ada',
  balance: 0,
  history: [],
  lastLogin: undefined,
  sessionId: 's-1'
}

As propriedades lastLogin e sessionId existem com o valor undefined porque campos de classe são campos JavaScript de verdade com target ES2022. O ! remove a verificação sem acrescentar nenhuma proteção em tempo de execução, então prefira as outras formas. Essa flag depende de strictNullChecks; desativar essa também a desativa.

Ativando o strict em um projeto existente

Mudar um projeto grande para strict de uma vez pode gerar centenas de erros. Como strict é o padrão no TypeScript 7, atualizar um projeto cujo tsconfig.json nunca mencionou strict o ativa sozinho; escreva "strict": false se precisar do comportamento antigo durante a migração. Um caminho que mantém o build passando:

  1. Adicione "strict": true e desative as flags com mais erros, em geral "strictNullChecks": false e "noImplicitAny": false.
  2. Corrija os erros restantes, depois ative mais uma flag e repita.
  3. Para noImplicitAny, a maioria das correções são anotações de parâmetros. Para strictNullChecks, adicione | undefined onde os valores podem faltar e depois trate isso com ?., ?? ou uma verificação if.
  4. Onde uma correção precisa esperar, coloque // @ts-expect-error com um motivo na linha. Ao contrário de @ts-ignore, ele aponta um erro quando o problema some, então a lista diminui sozinha.

Não recorra a as any ou ! para silenciar erros em massa: cada um esconde exatamente o bug que a flag foi criada para encontrar.

Flags úteis que o strict não inclui

Elas são separadas porque rejeitam código que muitas vezes está correto. Mesmo assim, muitos projetos as ativam.

FlagO que faz
noUncheckedIndexedAccessarr[i] e record[key] incluem undefined no tipo
exactOptionalPropertyTypesdebug?: boolean aceita uma chave ausente, mas não debug: undefined
noImplicitReturnstodo caminho de uma função com valor de retorno precisa retornar (TS7030)
noImplicitOverrideum método que sobrescreve um método da classe base precisa dizer override (TS4114)
noFallthroughCasesInSwitchum case não vazio precisa terminar com break, return ou throw (TS7029)
noUnusedLocals, noUnusedParametersvariáveis e parâmetros não usados são erros
noPropertyAccessFromIndexSignaturechaves de uma index signature precisam usar obj["key"], não obj.key

noUncheckedIndexedAccess é a que pega mais bugs reais. Com ela ativada:

const scores = [90, 85];
const d: Record<string, number> = {};

const third: number = scores[2]; // error TS2322: Type 'number | undefined' is not assignable to type 'number'.
const c: number = d["x"];        // same error

const safe = scores[2] ?? 0;     // number
for (const s of scores) {        // for...of is not affected: s is number
    console.log(s);
}

No TypeScript 7, tsc --init ativa noUncheckedIndexedAccess e exactOptionalPropertyTypes na configuração que gera, ao lado de strict.

Perguntas frequentes

O que o strict mode faz no TypeScript?

"strict": true ativa um grupo de verificações mais rígidas: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables e strictBuiltinIteratorReturn. Juntas, elas impedem que any apareça sem aviso e tornam null e undefined parte do sistema de tipos.

O strict mode vem ativado por padrão no TypeScript?

No TypeScript 7, sim: strict tem valor padrão true, então um projeto sem nenhuma configuração de strict recebe todas as verificações estritas. tsc --init também escreve "strict": true explicitamente. Para desativar, você precisa escrever "strict": false.

Posso desativar uma verificação do strict e manter as outras?

Sim. As flags individuais têm prioridade sobre strict: { "strict": true, "strictNullChecks": false } mantém todas as verificações estritas, exceto a de null. Essa é a forma usual de migrar um projeto grande uma flag por vez.

O strict mode do TypeScript é a mesma coisa que o "use strict" do JavaScript?

Não. "use strict" é um modo de execução do JavaScript que muda o comportamento do código. O strict do TypeScript só muda o que o verificador de tipos aponta. O TypeScript 7 sempre gera "use strict" em saídas que não são módulos, e alwaysStrict: false agora é uma opção removida.

O strict inclui noUncheckedIndexedAccess?

Não. noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitReturns, noImplicitOverride e noFallthroughCasesInSwitch são flags separadas que você ativa por conta própria. tsc --init ativa as duas primeiras na configuração que gera.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR