BeCuriouzBeCuriouz

Learn something new every day

🔷 TypeScript
🕳️

Any-Creep and Unsafe Casts: How Type Safety Leaks Away

💡 any and as don't make code safe — they make the compiler stop checking; prefer unknown plus real validation at every boundary.

You've built strict, well-typed code — but two habits quietly drain that safety back out. The first is any-creep: one any spreads because any expression touching any becomes any. Read a field off an any, pass it along, and the type checker simply stops looking. any also disables autocomplete and lets typos compile.

ts
const data: any = JSON.parse(res);
const id = data.user.id;   // id: any — no checking
const n: number = id;      // compiles, even if id is a string!

The fix is unknown, the type-safe counterpart. Like any it accepts anything, but unlike any it forbids using the value until you narrow it, forcing a check at the boundary:

ts
const data: unknown = JSON.parse(res);
// data.user  ❌ Error: 'data' is of type 'unknown'
if (typeof data === "object" && data && "user" in data) { /* narrow first */ }

The second leak is the unsafe assertion — as. Writing value as User doesn't convert or check anything; it just silences the compiler and asserts you're right. If you're wrong, the error surfaces later as a runtime crash. The double-cast x as unknown as T is a louder version of the same lie, and the non-null ! (as in el!.value) asserts "not null" with zero proof.

The discipline: keep any out entirely (noImplicitAny, and lint rules like no-explicit-any), type external inputs as unknown and validate them — with a type guard or a schema library like Zod — instead of asserting. Reserve as for cases the compiler genuinely can't see, and treat every as/! as a claim you now own.

🕳️ Any-Creep and Unsafe Casts: How Type Safety Leaks Away — BeCuriouz