type-fest
type-fest copied to clipboard
Add `ArrayAt` type for stricter `Array.prototype.at()` with tuples
See https://github.com/sindresorhus/ts-extras/issues/39 and https://github.com/microsoft/TypeScript/issues/47660.
const tuple = ['abc', 123, true] as const;
type First = ArrayAt<typeof tuple, 0>; // 'abc'
type Last = ArrayAt<typeof tuple, -1>; // true
type SecondToLast = ArrayAt<typeof tuple, -2>; // 123
type ThirdToLast = ArrayAt<typeof tuple, -3>; // 'abc'
type OutOfBounds = ArrayAt<typeof tuple, 999>; // should not compile since 999 does not extend 0 | 1 | 2 | -1 | -2 | -3
const array = ['abc', 123, true];
type First = ArrayAt<typeof tuple, 0>; // string | number | true
type Last = ArrayAt<typeof tuple, -1>; // string | number | true
type OutOfBounds = ArrayAt<typeof tuple, 999>; // string | number | true
PR welcome
Per discussion in https://github.com/sindresorhus/ts-extras/issues/39, should this be TupleAt
?
If we call this type TupleAt
how would behavior with non-tuples work? Disallow non-tuple inputs? Rename but still support plain arrays?
Why would you use it with non-tuples? It has no benefit.
I'm thinking of cases where users might have a type param for an array or a tuple which is passed to this type. Might be good to gracefully handle those. Not sure if this would be an actual pain point though.
Then I suggest we do two types:
-
TupleAt
-
ArrayAt
What would the behavior of ArrayAt
be? Would it be any different than typeof array[number]
?
What would the behavior of
ArrayAt
be? Would it be any different thantypeof array[number]
?
ArrayAt<Array, -1>
should be the same as LastArrayElement<Array>
For arrays I would expect string
and boolean
for First
and Last
respectively.
const array = ['abc', 123, true];
type First = ArrayAt<typeof array, 0>; // string
type Last = ArrayAt<typeof array, -1>; // boolean
Then I suggest we do two types:
TupleAt
ArrayAt
@sindresorhus But what if we have an array type T
that sometimes is a tuple and sometimes not? If TupleAt
and ArrayAt
are segregated, then we won't be able to use any of them with T
. I propose the following:
type T = number[] | [true, false];
type X = ArrayAt<T, -1>; // Should be `number | false`, IMO