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
Array .at()
on readonly tuples
#100
Comments
As long as the index is positive, the following works pretty well: interface ReadonlyArray<T> {
at<I extends number>(index: I): this[I];
} We can detect (and extract from) negative numbers with something like: interface ReadonlyArray<T> {
at<I extends number>(index: I): `${I}` extends `-${infer J extends number}` ? T | undefined : this[I];
} But at that point I'm only typing it as We can bring in a classic bit of array length maths: type Length<T extends any[]> = T extends { length: infer L } ? L : never
type BuildTuple<L extends number, T extends any[] = []> = T extends { length: L } ? T : BuildTuple<L, [...T, any]>
type Subtract<A extends number, B extends number> = BuildTuple<A> extends [...(infer U), ...BuildTuple<B>]
? Length<U>
: never
interface ReadonlyArray<T> {
at<I extends number> (index: I): `${I}` extends `-${infer J extends number}`
? this[Subtract<this["length"], J>]
: this[I]
} Now we're able to type the negative indexes too, but only as long as they're smaller than the length, so we need to detect a negative number again: interface ReadonlyArray<T> {
at<I extends number> (index: I): `${I}` extends `-${infer J extends number}`
? `${Subtract<this["length"], J>}` extends `-${number}`
? undefined
: this[Subtract<this["length"], J>]
: this[I]
} And here's the final result: const a = [false, 1, '2'] as const
const b = a.at(0)
// ^? const b: false
const c = a.at(-1)
// ^? const c: "2"
const d = a.at(-4)
// ^? const d: undefined |
Hmmmm, I think I'm happy with the current workaround, which is to just use |
FYI here is the implementation in type-plus: |
Unless there is a good reason for typescript not to return the correct type when accessing a tuple with
.at
it feels like a good candidate for this library.This is how it is currently:
But with this library it could be:
The text was updated successfully, but these errors were encountered: