Pular para o conteúdo principal

Null Safety & Optionals

Lidar com valores null/nil é uma fonte comum de bugs. Veja como diferentes linguagens abordam a segurança contra null.

Tipos Nullable & Optionals​

// null and undefined are distinct
let a = null; // Intentionally empty
let b = undefined; // Not yet assigned
let c; // undefined

// Checking for null/undefined
if (value === null) { }
if (value === undefined) { }
if (value == null) { } // checks both null & undefined

// Nullish coalescing (??)
const name = user ?? "default";
const age = data.age ?? 0;

// Optional chaining (?.)
const city = user?.address?.city;
const first = arr?.[0];
const result = func?.();

// Nullish coalescing assignment
let x = null;
x ??= "default"; // x is now "default"

// Logical OR (includes falsy values)
const name2 = user || "default"; // "" -> "default"
const name3 = user ?? "default"; // "" -> ""

Principais Conclusões​

  • Tipos Option/Optional -- Rust (Option<T>), Swift (T?), Zig (?T) e Java (Optional<T>) fornecem tipos opcionais explícitos em vez de referências anuláveis. Em Rust, let x: Option<i32> = Some(42) ou None -- não existe null; você usa match, if let ou unwrap_or(0). O var name: String? = nil do Swift e o var value: ?i32 = null do Zig tornam a opcionalidade parte do tipo. O Optional<String> opt = Optional.ofNullable(name) do Java encapsula valores anuláveis. Esses tipos forçam você a tratar a ausência explicitamente. Escolha Option/Optional quando quiser verificação em tempo de compilação; use referências anuláveis (JavaScript, Python, C) quando preferir flexibilidade e verificações em tempo de execução.

  • Operadores de coalescência nula -- A maioria das linguagens suporta ?? para valores padrão: const name = user ?? "default" em JavaScript, $name = $user ?? "default" em PHP, string name = user ?? "default" em C#, let result = name ?? "default" em Swift e const result = value orelse 0 em Zig. Esses ignoram valores falsy como "" ou 0 (diferente de || em JavaScript). Go não tem ??; você usa if user != nil { name = user.Name } else { name = "default" } ou funções auxiliares. Escolha linguagens com ?? quando precisar frequentemente de valores padrão seguros; em Go, encapsule os padrões em pequenas funções auxiliares.

  • Linguagens que eliminam null -- Rust não tem null; valores opcionais usam Option<T>. Swift e Zig usam tipos opcionais como mecanismo principal: em Swift, String? é distinto de String, e o desempacotamento com ! ou if let é explícito. O ?T do Zig força orelse ou if para tratar null. Isso evita o "erro de um bilhão de dólares" das desreferências nulas. Python, JavaScript, Java e C permitem null/None/undefined em qualquer lugar, levando a NullPointerException ou TypeError em tempo de execução. Se eliminar bugs de null é prioridade, escolha Rust; Swift e Zig oferecem tratamento forte de opcionais com menos rigidez que Rust.

  • Navegação segura -- Encadeamento opcional (?.) em JavaScript, PHP, C#, Swift e Ruby previne erros de desreferência nula ao percorrer estruturas aninhadas. Por exemplo, user?.address?.city retorna undefined ou nil se qualquer elo for null em vez de lançar exceção. O arr?.[0] e func?.() do JavaScript estendem isso para arrays e chamadas. Sem ?., você escreve user && user.address && user.address.city (JavaScript) ou verificações if aninhadas. Go não tem ?.; você verifica if user != nil && user.Address != nil { city = user.Address.City }. Prefira ?. ao trabalhar com dados profundamente aninhados e fracamente tipados (APIs, configurações).

  • Atribuição com coalescência nula -- JavaScript (x ??= "default"), PHP ($name ??= "default") e C# (name ??= "default") atribuem um padrão apenas quando a variável é null ou undefined. Isso mantém o código conciso ao inicializar campos opcionais. Go e Rust exigem if ou match explícitos. Use ??= quando tiver configuração opcional ou padrões lazy; em Go e Rust, use padrões Option/if para maior clareza.