Rats!
Where TypeScript doesn't save you, or doesn't do what you want.
- Lossy type downcasting
- Infinity is not of type Infinity
- Uninitialized self-reference not caught in IIFE
- Numbers permitted in string index type
Lossy type downcasting
let t: { a: number } = { a: 1 };
let u: {} = t;
let v: { a?: string } = u;
if (v.a !== undefined) {
alert(v.a.toUpperCase()); // boom!
}
This typechecks, but because TS does not require verification of downcast value's shape, this code blows up.
Infinity is not of type Infinity
type Inf = 178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123721178312789361972639173621978361987263912736123;
const n: Inf = Infinity;
The giant number on the RHS of Inf
evaluates to Infinity
in a JS
interpreter, so TS types Inf
as Infinity
(verify by hovering over the type
alias).
But the Infinity
value is not assignable to a value of type Inf
because the
Infinity
value is a number type. Makes sense.
Uninitialized self-reference not caught in IIFE
let c: any = (() => c)();
TypeScript thinks c
is in scope of the IIFE, but in fact is not initialized until after the IIFE
is evaluated. At runtime, this throws a reference error.
Numbers permitted in string index type
const map: {[k: string]: string} = {
1: '',
}
This typechecks, but const map: {[k: number]: string} = {'one': ''}
wouldn't. The runtime types
are semantically correct because object properties are strings, but accepting a number where strings
are expected isn't desirable during development.