If you must adhere to this method instead of utilizing tuples, you have the option to specify the array's length using the length
property, ensuring that the passed array matches that specific length.
type FixedLengthArray<T, Length extends number = number> = readonly T[] & {
length: Length
}
function foo(arr: FixedLengthArray<number, 3>) {
// Perform actions
}
foo([1, 2, 3, 4] as const);
/*
Argument of type 'readonly [1, 2, 3, 4]' is not assignable to parameter of type 'FixedLengthArray<number, 3>'.
Type 'readonly [1, 2, 3, 4]' is not assignable to type '{ length: 3; }'.
Types of property 'length' are incompatible.
Type '4' is not assignable to type '3'.ts(2345)
*/
The use of as const
is crucial in fixing the length of the array, rather than leaving it open as a general number
.
This precaution mirrors real-life scenarios since the length of a standard array can fluctuate, and thus verification should only pass if the length is definitively set.
You have the choice of employing either as const
or asserting the array's type:
// as const
const arr1 = [1, 2, 3] as const
foo(arr1)
// Type Assertion
type SetLength<T extends any[], Length extends number> = T & {
length: Length;
};
const arr2 = [1, 2, 3]
foo(arr as SetLength<typeof arr, 3>)