Skip to content

Empty array ([]) inferred to be never[] instead of [] or undefined[] #51979

Closed
@maranomynet

Description

@maranomynet

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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions