Strictmode: entendendo cada flag do strict
1. O que é o strict mode e por que ativá-lo?
O strict mode no TypeScript é uma configuração que ativa um conjunto de verificações rigorosas de tipo, definido pela propriedade strict: true no tsconfig.json. Quando ativado, ele habilita automaticamente todas as flags individuais de strict, proporcionando a máxima segurança de tipos possível.
// tsconfig.json
{
"compilerOptions": {
"strict": true
}
}
A diferença crucial entre ativar strict: true completo versus flags individuais é que o modo completo garante que nenhuma verificação crítica seja esquecida. Os benefícios incluem captura de erros em tempo de compilação, segurança de tipos aprimorada e código mais previsível.
2. strictNullChecks – O fim dos null/undefined silenciosos
Esta flag impede que null e undefined sejam atribuíveis a qualquer tipo, eliminando uma das fontes mais comuns de bugs em JavaScript.
// Sem strictNullChecks
let nome: string = null; // Permitido (perigoso!)
// Com strictNullChecks
let nome: string = null; // Erro: Type 'null' is not assignable to type 'string'
O impacto é significativo em parâmetros opcionais e retornos de função:
function encontrarUsuario(id: number): string | undefined {
// Lógica de busca
if (id === 0) return undefined;
return "João";
}
const usuario = encontrarUsuario(0);
console.log(usuario.toUpperCase()); // Erro: Object is possibly 'undefined'
Estratégias de mitigação incluem narrowing, operador ! e optional chaining:
// Narrowing
if (usuario !== undefined) {
console.log(usuario.toUpperCase()); // OK
}
// Non-null assertion (use com cuidado!)
console.log(usuario!.toUpperCase());
// Optional chaining
console.log(usuario?.toUpperCase());
3. noImplicitAny – Exigindo tipos explícitos
TypeScript infere any implicitamente quando não consegue determinar o tipo, o que pode levar a erros silenciosos em tempo de execução.
// Sem noImplicitAny
function processar(dado) {
return dado.length; // any implícito - sem verificação
}
// Com noImplicitAny
function processar(dado: any) {
return dado.length; // OK - explícito
}
function processar(dado: string) {
return dado.length; // Melhor - tipado corretamente
}
Casos comuns incluem parâmetros de função não tipados e callbacks:
// Exemplo com callback
function executar(fn) { // Erro: Parameter 'fn' implicitly has 'any' type
fn(42);
}
// Correção
function executar(fn: (x: number) => void) {
fn(42);
}
noImplicitReturns complementa essa flag garantindo que funções com retorno explícito sempre retornem um valor:
function obterValor(flag: boolean): string {
if (flag) {
return "ativo";
}
// Erro: Not all code paths return a value
}
4. strictFunctionTypes – Segurança na covariância/contravariância
Esta flag corrige um comportamento perigoso onde parâmetros de função são tratados como bivariantes (permitindo tanto covariância quanto contravariância).
// Sem strictFunctionTypes (bivariante)
type Animal = { nome: string };
type Cachorro = Animal & { latir(): void };
function processarAnimais(animais: Animal[]) {}
function processarCachorros(cachorros: Cachorro[]) {}
let animais: Animal[] = [];
let cachorros: Cachorro[] = [];
animais = cachorros; // Permitido (covariante)
cachorros = animais; // Permitido (perigoso!)
// Com strictFunctionTypes (contravariante)
type Processador<T> = (item: T) => void;
let processarAnimal: Processador<Animal> = (a) => {};
let processarCachorro: Processador<Cachorro> = (c) => {};
processarAnimal = processarCachorro; // Erro! (correto)
processarCachorro = processarAnimal; // Permitido (seguro)
5. strictBindCallApply – Tipando métodos de contexto dinâmico
Esta flag adiciona assinaturas de tipo mais rigorosas para bind, call e apply, prevenindo erros comuns com o contexto this.
// Sem strictBindCallApply
function saudacao(this: { nome: string }) {
return `Olá, ${this.nome}!`;
}
const contexto = { nome: "Maria" };
const saudacaoBind = saudacao.bind(contexto); // any
// Com strictBindCallApply
const saudacaoBind = saudacao.bind(contexto); // () => string - tipado corretamente!
// Exemplo com classe
class Contador {
private valor = 0;
incrementar() {
this.valor++;
}
criarCallback() {
// Sem strictBindCallApply, isso poderia causar erros
return this.incrementar.bind(this);
}
}
6. noUnusedLocals e noUnusedParameters – Código limpo e sem ruído
Essas flags eliminam variáveis e parâmetros não utilizados, mantendo o código mais limpo e fácil de manter.
// Sem noUnusedLocals
function calcular() {
const resultado = 42; // Aviso: 'resultado' is declared but its value never read
const temp = 10;
return temp * 2;
}
// Com noUnusedLocals
function calcular() {
const temp = 10;
return temp * 2;
}
// Parâmetros não utilizados
function log(mensagem: string, _nivel: number) {
console.log(mensagem);
// _nivel prefixado com _ indica uso intencionalmente ignorado
}
7. exactOptionalPropertyTypes e useUnknownInCatchVariables – Flags menos conhecidas
exactOptionalPropertyTypes
Esta flag impede que propriedades opcionais recebam undefined sem declaração explícita:
// Sem exactOptionalPropertyTypes
interface Config {
timeout?: number;
}
const config: Config = { timeout: undefined }; // Permitido
// Com exactOptionalPropertyTypes
const config: Config = { timeout: undefined }; // Erro!
const config: Config = { timeout: 5000 }; // OK
const config: Config = {}; // OK
useUnknownInCatchVariables
Força variáveis de catch a serem unknown em vez de any, promovendo tratamento de erro mais seguro:
// Sem useUnknownInCatchVariables
try {
JSON.parse("inválido");
} catch (erro) {
console.log(erro.message); // any - sem verificação
}
// Com useUnknownInCatchVariables
try {
JSON.parse("inválido");
} catch (erro: unknown) {
if (erro instanceof Error) {
console.log(erro.message); // OK - verificado
}
console.log(erro.message); // Erro: Object is of type 'unknown'
}
Referências
- TypeScript Documentation: Compiler Options in MSBuild — Documentação oficial sobre todas as flags de compilação do TypeScript
- TypeScript Handbook: Strict Mode — Guia oficial explicando cada flag do strict mode
- TypeScript Deep Dive: Strict Mode — Artigo técnico detalhado sobre strict mode e suas implicações
- Microsoft TypeScript Blog: Strict Mode Improvements — Post oficial sobre melhorias no strict mode no TypeScript 4.4
- TypeScript ESLint: Strict Mode Rules — Documentação de regras ESLint que complementam o strict mode do TypeScript
- Understanding TypeScript's Strict Mode — Playground oficial do TypeScript para testar flags strict interativamente