-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Array.prototype.at
should return a more precise type when operating on a tuple
#47660
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
I don’t think there’s a way to handle negative indices without the compiler special-casing |
Array.prototype.at
should return a more precises type when operating on a tupleArray.prototype.at
should return a more precise type when operating on a tuple
You can get negative indices to work for tuples (template literals to drop the minus sign and then use the numberlike string to index into a shifted reversed tuple), but nobody would want this in the actual TS library. Still, enjoy: ⚙🛠type Reverse<T extends readonly any[], U extends any[] = []> =
T extends readonly [infer F, ...infer R] ? Reverse<R, [F, ...U]> : U
type At<T extends readonly any[], I extends number> =
`${I}` extends `-${infer J}` ? [never, ...Reverse<T>] extends infer R ? J extends keyof R ? R[J] :
undefined : never : T[I];
interface ReadonlyArray<T> {
at<I extends number>(index: I): At<this, I>;
}
interface Array<T> {
at<I extends number>(index: I): At<this, I>;
} const tuple = [1, 2, 3] as const;
const element = tuple.at(1);
type T = typeof element; // 2
const element2 = tuple.at(-1);
type U = typeof element2; 3
const element3 = tuple.at(100);
type V = typeof element3; // undefined |
For positive indices I really don't see a reason not to use @jcalz ow my soul |
Like small numbers could at least just be hardcoded right? This seems to work fine in the playground: declare global {
interface ReadonlyArray<T> {
at<R>(this: readonly [...any[], R], index: -1): R;
}
}
const a = [1,'foo', { x: 10 }] as const;
const z = a.at(-1); |
Yeah, if support for positive indexes and -1 are added, that should handle most use cases. |
@RyanCavanaugh ah yes, the theological argument for #26382 |
The return type of let a = [Array(0), Array(0)]
let b: number = a[2] |
Had this problem, I think @Jamesernator's code should be: declare global {
interface ReadonlyArray<T> {
at<R>(this: readonly [...any[], R], index: number): R;
}
} so it allows reference by any index |
@wesbos That type is not correct, const instruments = ["guitar", "drums", "base", "vocals", "keys"] as const
type Instrument = typeof instruments[number];
let value = instruments.at(2);
// ^? "keys" |
@wesbos I think you want something more like this: interface ReadonlyArray<T> {
at<R extends ReadonlyArray<T>, I extends keyof R>(this: readonly [...R], index: I): R[I];
} |
@jamiebuilds hmm.. Works for me, your playground correctly logs the 3rd item |
@jamiebuilds Why do you need |
This issue has been marked as "Too Complex" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
"Too Complex" mean, i am too lazy to code, but if you give me 1M$ , i will do it. |
Too complex? It would be nice if that undefined only showed up when relevant. There have even been suggested improvements in this topic. How to proceed? |
Suggestion
Extracted out of #45512
🔍 Search Terms
List of keywords you searched for before creating this issue. Write them down here so that others can find this suggestion more easily and help provide feedback.
Tuple Array.prototype.at
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
at
called on a tuple should work consistently with how index access on tuples works.📃 Motivating Example
This is how tuples work when using index access.
💻 Use Cases
Preferring
.at(index)
to[index]
.Partial Hack Solution
as suggested by @djmisterjon
The text was updated successfully, but these errors were encountered: