Skip to content

Add EmptyArray type - #1513

Open
vjymisal0 wants to merge 3 commits into
sindresorhus:mainfrom
vjymisal0:add-empty-array-type
Open

vjymisal0 wants to merge 3 commits into
sindresorhus:mainfrom
vjymisal0:add-empty-array-type

Conversation

@vjymisal0

Copy link
Copy Markdown

Adds EmptyArray (and a companion IsEmptyArray), mirroring the existing EmptyObject/IsEmptyObject pair.

Closes #929

unknown[]/any[] can't represent a strictly empty array — this is the array equivalent of the {}-vs-EmptyObject problem already solved for objects. Modeled as readonly [], matching what [] as const already produces (as noted in the issue).

  • source/empty-array.d.tsEmptyArray + IsEmptyArray, following the empty-object.d.ts doc/test conventions
  • test-d/empty-array.ts — assignability, mutation rejection, and union-narrowing tests, plus any/never/unknown-style edge cases
  • Registered in index.d.ts and readme.md

npm test (tsc, tsd, xo) passes locally.

@sindresorhus

Copy link
Copy Markdown
Owner

I think EmptyArray itself is reasonable for discoverability, since that is what #929 asks for, even though the underlying type is simply readonly [] and a value can already use [] as const.

I am less convinced about adding IsEmptyArray. The issue does not ask for it, the PR does not show a concrete use case for it, and users can already write T extends readonly [] directly. I would keep this focused on EmptyArray unless there is a convincing use case for the predicate. EmptyObject is different becuase {} cannot express a strictly empty object, while readonly [] already expresses an empty tuple exactly.

If we do keep IsEmptyArray, it has a bug for never:

type Result = IsEmptyArray<never>;
//=> never

type Branch = IsEmptyArray<never> extends true ? 'empty' : 'not empty';
//=> 'empty'

The type says it returns a boolean, and the existing IsTuple<never> returns false, so this should explicitly handle never before the distributive conditional.

The tests are also missing the boundary cases mentioned in the PR description. At minimum, I would cover never as false, any as boolean, unknown as false, readonly [] as true, readonly non-empty tuples and arrays as false, optional tuples, never[], and a mixed [] | [number] union as boolean.

The current index assignment test does not actually verify readonly behavior because it also fails for mutable [], which has no element at index 0. A negative foo.push() test would distinguish readonly [] from [].

The documentation should also link to #929 and briefly explain that the implementation is a readonly empty tuple, as requested by the contribution guide. If the predicate stays distributive, its union behavior should be documented too, since “strictly equal” suggests that IsEmptyArray<[] | [number]> would simply be false rather than boolean.

@vjymisal0
vjymisal0 force-pushed the add-empty-array-type branch from ac4fcdb to 91e612d Compare September 9, 2026 11:56
@vjymisal0

Copy link
Copy Markdown
Author

Thanks for the careful review. I kept the PR focused on EmptyArray and removed the predicate rather than introducing a second API without a concrete use case. I also added the issue link and documented that it is implemented as readonly []; the tests now cover readonly assignment and mutation behavior. The latest branch is commit 91e612d.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EmptyArray type

2 participants