Unsafe any Assignment

ID

javascript.ts_no_unsafe_assignment

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

reliability, type-safety, typescript

Description

Reports a TypeScript declaration whose left-hand type annotation is something other than any / unknown, but whose initialiser carries no resolvable type (the most common case being a value of type any):

declare function read(): any;

const value: string = read();   // FLAW — any flows into string

Rationale

A variable declared with a precise type but initialised from any looks like a string to every later reader and tool, but at runtime it can be anything. The first method call (.toUpperCase(), .trim(), …​) on a non-string runs into a TypeError, and the type system gave no warning because the upstream any defeats the check.

The fix is one of:

  • narrow the value before the assignment (typeof, instanceof, a custom guard),

  • use an explicit as T cast that documents the assumption,

  • widen the variable’s type to any if untyped really is the intent (and accept that callers must narrow).

Remediation

const raw = read();
if (typeof raw === "string") {
  const value: string = raw;   // OK — narrowed
}

const value = read() as string;        // explicit assumption
const value: any = read();             // explicit opt-out

Notes

The rule fires only in TypeScript files, on lexical declarations (let / const) with an explicit type annotation. Declarations annotated as any or unknown are not flagged — those already carry the warning. The "rhs is any" signal comes from sankxy’s TypeUtil, which marks unresolved or unannotated values as Unknown. As a result, the rule may also fire on values whose type sankxy could not infer (e.g. dynamic imports), not only on literal any — a conservative trade-off, since both cases lose the type guarantee at runtime.