rivo
Version:
🤖 The ultimate library you need for composable type-level programming in TypeScript, powered by HKT.
48 lines (45 loc) • 1.4 kB
TypeScript
import type { Ary } from ".";
import type { Args, Fn } from "../HKT";
import type IsNatFn from "../Num/Nat/IsNat";
import type { Filter } from "../Union/Filter";
import type { If, IsAny, IsNever, Not } from "../helpers";
/**
* Check if an {@link Ary} (i.e., `Array` or `ReadonlyArray`) is a tuple.
*
* Sig: `(a: Ary) => boolean`
*
* @example
* ```typescript
* type R1 = IsTuple<string[]>;
* // ^?: false
* type R2 = IsTuple<readonly number[]>;
* // ^?: false
* type R3 = IsTuple<["foo", "bar"]>;
* // ^?: true
* type R4 = IsTuple<readonly [42, 1337, ...string[]]>;
* // ^?: true
* type R6 = IsTuple<readonly [...string[]]>;
* // ^?: false, because `readonly [...string[]]` is actually equal to `readonly string[]`, and
* // the same is true for something like `[...(number | string)[]]`, which is equal to
* // `(number | string)[]`, etc.
* type R7 = IsTuple<[]>;
* // ^?: true
* ```
*/
export type IsTuple<A extends Ary> = If<
IsAny<A>,
boolean,
A extends A ?
A["length"] extends 0 ?
true
: Not<IsNever<Filter<IsNatFn, Exclude<keyof A, keyof [] | keyof (readonly [])>>>>
: never
>;
/**
* [Fn] Check if an {@link Ary} (i.e., `Array` or `ReadonlyArray`) is a tuple.
*
* Sig: `(a: Ary) => boolean`
*/
export default interface IsTupleFn extends Fn<[Ary], boolean> {
def: ([a]: Args<this>) => IsTuple<typeof a>;
}