Distinguishing tuples from indefinite length arrays: An application of IsProperFiniteUnion and IsNaturalNumber
1 min readJan 21, 2021
A combination of my types IsProperFiniteUnion
and IsNaturalNumber
can be used to construe a type IsTuple
that distinguishes indefinite length array types such as number[]
from tuple types, i.e. array types with a fixed, finite length, such as [string, string, string]
:
// Checks whether the given type is a tuple, i.e. a (possibly
// readonly) array type with a fixed finite length. Evaluates
// always to either `true` or `false`.
// Examples:
// IsTuple<number[]> ⟶ false
// IsTuple<[number, number]> ⟶ true
type IsTuple<T> =
IsProperFiniteUnion<T> extends true
? false
: (T extends PossiblyImmutableArray
? (T extends { length: infer ElementCount }
? (IsNaturalNumber<ElementCount> extends true
? true
: false)
: Impossible)
: false);const testIsTuple1: IsTuple<5> = false;
const testIsTuple2: IsTuple<[5]> = true;
const testIsTuple3: IsTuple<[5, boolean, number]> = true;
const testIsTuple4: IsTuple<number[]> = false;
const testIsTuple5: IsTuple<readonly number[]> = false;
const testIsTuple6: IsTuple<readonly [5, boolean, number]> = true;
const testIsTuple7: IsTuple<[number[]]> = true;
const testIsTuple8: IsTuple<[string, string, string, string,
boolean, number, string]> = true;
const testIsTuple9: IsTuple<[number, string] | [string, number]>
= false;
with auxiliary type PossiblyImmutableArray
:
type PossiblyImmutableArray = readonly unknown[];
Note that readonly arrays are not considered specializations of respective mutable array types but the other way round, what is a bit counterintuitive to my mind:
const testReadonlyArray1:
(readonly number[] extends number[] ? true : false) = false;
const testReadonlyArray2:
(number[] extends readonly number[] ? true : false) = true;