-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Provide declaration of sparse array #48637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is what |
Majority of arrays are still dense arrays, for which getter wouldn't return |
Even for dense arrays, the type system doesn't prevent you from indexing out of range: const arr = [ 1, 2, 3 ];
const x = arr[3]; // x: number
console.log(x); // ...but x is actually undefined at runtime! Sparse arrays have the additional caveat that you might have gaps inside |
At any rate, if you don't want to use the global |
That's right. It is less a problem when accessing out-of-boundary returns an
Yeah, it can't be a pure lib update, but it may not need a special syntax like that. An alternative is to allow declaring getter and setter with different types in interface. |
The idea of specifically marking a list as sparse makes sense to me, so a developer will know that it behaves more like a dictionary with numbers as keys, just that it also has those iteration methods. |
This definitely sounds like a bug. |
A trimmed down version of the type checker issue has been reported in #50351. It would still be good if TypeScript can provide a sparse array type, though. |
lib Update Request
While majority of arrays in JavaScript / TypeScript are dense arrays, occasionally there are use cases for sparse array. (We are using it in Canva for some core data structures.)
Sparse array has some interesting behavior different from a dense array, for example, all the methods iterating it (like
forEach
,map
,every
, etc.) only visits occupied slots, while@@iterator
and index access (for index < length) can visit empty slots withundefined
.I've done some spike to declare sparse array as an interface with a subset of array, and so far I have:
It seemingly works fine to some extent, with two issues (apart from all the things lacked currently) I see:
First, it has problem with assigning dense array to the type. Ideally, a dense array can be assigned to a variable with sparse array type, but not the reverse. When
T
is simple, it works as expected, however, whenT
gets more complicated, the assignment sometimes gets mysteriously rejected with something like:However, if I add a simple assignment to the start of a file with this kind of errors, e.g.
const _a: SparseArray<string> = ['a'];
, then all the errors go away in that file. This is likely a bug in TypeScript's type checker that I haven't been able to construct a minimal reproducible example for (will create a separate issue if I can construct it).Second, the type for index definition is actually wrong. It should really have a getter returning
T | undefined
, but a setter only acceptingT
, becauseundefined
should only be accepted for a sparse array ofT | undefined
, not a sparse array ofT
, since it would turn an empty slot into an occupied slot withundefined
, affecting behavior of the iterating methods. But as far as I know, there is no way to declare different type for setter and getter on interface in TypeScript.Given all these challenges and that it's an existing thing in JavaScript, I think it would be good to have the type declarations provided by TypeScript directly.
The text was updated successfully, but these errors were encountered: