type-plus
Version:
Provides additional types for TypeScript.
84 lines (79 loc) • 1.98 kB
text/typescript
import type { IsAny } from '../any/any_type.js'
import type { IsEqual } from '../equal/equal.js'
import type { Abs } from '../math/abs.js'
import type { GreaterThan } from '../math/greater_than.js'
import type { Subtract } from '../math/subtract.js'
import type { IsNever } from '../never/never_type.js'
import type { StrictNumberType } from '../number/strict_number_type.js'
import type { Integer } from '../numeric/integer.js'
import type { Negative } from '../numeric/negative.js'
/**
* Gets the normalized index to access the element of an array or tuple.
*
* ```ts
* type R = IndexAt<['a', 'b', 'c'], 2> // 2
* type R = IndexAt<['a', 'b', 'c'], -2> // 1
*
* type R = IndexAt<['a', 'b', 'c'], 3> // never
* type R = IndexAt<['a', 'b', 'c'], -4> // never
* ```
*/
export type IndexAt<
A extends Array<unknown>,
N extends number,
Fail = never,
Upper = A['length'],
Lower = 0
> = IsNever<A, Fail, IndexAt._<A, N, Fail, Upper, Lower>>
export namespace IndexAt {
export type _<
A extends Array<unknown>,
N extends number,
Fail = never,
Upper = A['length'],
Lower = 0
> = IsEqual<
A['length'],
0,
Fail,
Integer<
N,
StrictNumberType<
A['length'],
// A: array
N,
// A: tuple
Negative<
N,
GreaterThan<Abs<N>, A['length']> extends true ? Lower : Subtract<A['length'], Abs<N>>,
GreaterThan<A['length'], N> extends true ? N : Upper
>
>,
// N: number or float
IsAny<
N,
number,
StrictNumberType<
N,
// TODO: handle tuple to union of indexes
N
>
>
>
>
}
/**
* Is N an out of bound index of A.
*
* ```ts
* type R = IsIndexOutOfBound<[1], 0> // false
* type R = IsIndexOutOfBound<[1], -1> // false
* type R = IsIndexOutOfBound<[1], 1> // true
* type R = IsIndexOutOfBound<[1], -2> // true
* ```
*/
export type IsIndexOutOfBound<A extends unknown[], N extends number, Then = true, Else = false> = IsNever<
IndexAt<A, N, never, never, never>,
Then,
Else
>