Skip to content
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

Feature Request: better typing for read-only array methods #133

Open
AntonPieper opened this issue Apr 4, 2023 · 2 comments
Open

Feature Request: better typing for read-only array methods #133

AntonPieper opened this issue Apr 4, 2023 · 2 comments

Comments

@AntonPieper
Copy link

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
Copy link
Author

AntonPieper commented Apr 4, 2023

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.

@nevnein
Copy link

nevnein commented Aug 29, 2023

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

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

No branches or pull requests

2 participants