ts-reset icon indicating copy to clipboard operation
ts-reset copied to clipboard

Feature Request: better typing for read-only array methods

Open AntonPieper opened this issue 2 years ago • 2 comments

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
  );

AntonPieper avatar Apr 04 '23 10:04 AntonPieper

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.

AntonPieper avatar Apr 04 '23 11:04 AntonPieper

FWIW I mentioned this issue in the use case collection concerning the revamp of array methods in the TS repo, here

nevnein avatar Aug 29 '23 14:08 nevnein