Feature Request: better typing for read-only array methods
read-only array methods like map get the index as number, which makes some operations cumbersome if setting "noUncheckedIndexedAccess": true in tsconfig.json:
const a = ["some", "values"] as const;
const b = ["other", "things"] as const;
const c = a.map((_, i) => a[i] + b[i]);
Proposal: type index as a tuple of all possible indices.
I also have a version of getting all possible indices of an array myself which does not use recursion. Maybe that helps implementing it:
type ToString<T extends number> = `${T}`;
type Indices<T extends readonly unknown[]> =
| {
[K in keyof T]:
K extends ToString<infer N>
? N
: never
}[number]
| (
number extends T["length"]
? number
: never
);
Here is a declaration I came up with:
declare interface ReadonlyArray<T> {
map<
U,
A extends readonly unknown[] = this extends readonly [...infer X] ? X : never,
I extends Indices<A> = Indices<A>
>(callbackfn: (value: A[I], index: I, array: A) => U, thisArg?: any): U[];
}
This also improves typing for the array parameter of callbackfn by actually creating a tuple type for array instead of an array of a union.
I could not yet get following working however: the index parameter is the union of all possible indices, however each iteration only ever has one possible index. This leads to following:
const a = ["some", "values"] as const;
const b = ["other", "things"] as const;
const c = a.map((_, i) => `${a[i]} ${b[i]}` as const);
// ^? "some other" | "some things" | ...
however a[i] and b[i] always refer to the same literal i, so "some things" can actually never occur.
FWIW I mentioned this issue in the use case collection concerning the revamp of array methods in the TS repo, here