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
| Flag | O que ela aponta | Erro |
|---|---|---|
noImplicitAny | um parâmetro ou variável cujo tipo seria any sem aviso | TS7006 Parameter 'x' implicitly has an 'any' type. |
strictNullChecks | usar um valor que pode ser null ou undefined | TS18048 'u' is possibly 'undefined'. |
strictFunctionTypes | atribuir uma função cujo tipo de parâmetro é mais estreito que o exigido | TS2322 |
strictBindCallApply | argumentos errados para .call, .bind e .apply | TS2345 |
strictPropertyInitialization | um campo de classe que nunca recebe valor | TS2564 Property 'name' has no initializer and is not definitely assigned in the constructor. |
noImplicitThis | this com tipo any implícito, como em uma function aninhada | TS2683 |
useUnknownInCatchVariables | usar a variável do catch antes de estreitá-la (ela é unknown) | TS18046 'err' is of type 'unknown'. |
strictBuiltinIteratorReturn | tratar it.next().value de um iterador nativo como sempre definido | TS2322 |
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:
- Adicione
"strict": truee desative as flags com mais erros, em geral"strictNullChecks": falsee"noImplicitAny": false. - Corrija os erros restantes, depois ative mais uma flag e repita.
- Para
noImplicitAny, a maioria das correções são anotações de parâmetros. ParastrictNullChecks, adicione| undefinedonde os valores podem faltar e depois trate isso com?.,??ou uma verificaçãoif. - Onde uma correção precisa esperar, coloque
// @ts-expect-errorcom 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.
| Flag | O que faz |
|---|---|
noUncheckedIndexedAccess | arr[i] e record[key] incluem undefined no tipo |
exactOptionalPropertyTypes | debug?: boolean aceita uma chave ausente, mas não debug: undefined |
noImplicitReturns | todo caminho de uma função com valor de retorno precisa retornar (TS7030) |
noImplicitOverride | um método que sobrescreve um método da classe base precisa dizer override (TS4114) |
noFallthroughCasesInSwitch | um case não vazio precisa terminar com break, return ou throw (TS7029) |
noUnusedLocals, noUnusedParameters | variáveis e parâmetros não usados são erros |
noPropertyAccessFromIndexSignature | chaves 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.