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 Tcast that documents the assumption, -
widen the variable’s type to
anyif 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.