Closed
Description
Bug Report
I ran into this behavior where TypeScript infers that an empty array (literal []
) to be of type never[]
, which it interprets to never happen and thus to be of no sigificance.
Runtime errors then ensue.
🔎 Search Terms
"never[]" array
🕗 Version & Regression Information
Affects all versions from 3.5.1 through 4.9.4 (and the nightly)
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about "common-bugs-that-arent-bugs"
⏯ Playground Link
Playground link with relevant code
💻 Code
const ret = Math.random() > 0.5 ? ['foo', 'bar'] as const : [];
// ^? const ret: readonly ['foo', 'bar'] | never[]
// @ts-expect-error (because `ret[0]` may be `undefined`)
const foo: string = ret[0]
// ^? (property) 0: "foo"
// @ts-expect-error (because `ret[1]` may be `undefined`)
const bar: string = ret[1]
// ^? (property) 1: "bar"
// 🔥🔥 This will throw a runtime error half the time. 🙀
console.log(
foo.toUpperCase(),
bar.toLocaleLowerCase()
)
🙁 Actual behavior
I get a TS error on the @ts-expect-error
comment as the ret
tuple is inferred to be effectively always ['foo', 'bar']
...and then I get runtime errors once I try and do .toUpperCase()
on the (sometimes undefined
) values.
🙂 Expected behavior
I'd expect the inferred type of ret
to be something like readonly ['foo', 'bar'] | []
or possibly readonly ['foo', 'bar'] | | Array<undefined>
.
To fix this I have to explicitly change the first line to either:
const ret = Math.random() > 0.5 ? ['foo', 'bar'] as const : [] as [];
…or:
const ret = Math.random() > 0.5 ? ['foo', 'bar'] as const : [] as const;