The documentation you referenced was likely accurate at the time of TypeScript 2.0's release. However, with the rollout of TypeScript 2.1, there was an introduction of enhanced any
inference, which was implemented in microsoft/TypeScript#11263.
Subsequently, enabling --noImplicitAny
caused a change where uninitialized or initialized to null
or undefined
non-const
variables would be inferred as type any
rather than null
or undefined
, even when --strictNullChecks
is activated. This applied to TypeScript code (as opposed to checking JavaScript files) as well:
let nLet = null; // any
let uLet = undefined; // any
var nVar = null; // any
var uVar = undefined; // any
const nConst = null; // null
const uConst = undefined; // undefined
The reasoning behind this seems to stem from the likelihood of modifying a variable initialized with null
or undefined
later on. The use of the any
type enables control flow analysis for further narrowing:
let x = undefined;
while (!x) {
if (Math.random() < 0.5) x = "finished";
}
x // string
x.toUpperCase(); // okay
x.toFixed(); // error
This scenario exemplifies how the compiler permits assignment of a string
to x
within the loop and recognizes its type once outside the loop, facilitating treatment exclusively as a string
.
Even during initial assignment, control flow analysis constrains the apparent type of these variables to null
and
undefined</code, demonstrating a distinction from merely annotating a variable as type <code>any
:
let nLet = null; // any
nLet.x // error, Object is possibly 'null'
let uLet = undefined; // any
uLet.x // error, Object is possibly 'undefined'
let aLet: any;
aLet.x // no error
In practical usage, minimal issues are expected when working with variables initialized to null
or undefined
.
Playground link showcasing the code