TypeScript: How to Constrain Array with Fixed Length

Updated: January 8, 2024 By: Guest Contributor Post a comment

Introduction

TypeScript enhances JavaScript productivity by adding types to variables and functions, significantly improving the developer experience. An intriguing aspect is setting arrays with a predetermined length, ensuring program correctness when the array size is part of your domain logic.

Understanding Fixed-length Arrays

Fixed-length arrays are critical in situations where the data structure’s size must be known at compile time for correctness and performance reasons. TypeScript’s tuple types offer a way to model fixed-length arrays, although they do not enforce length at runtime.

let fixedArray: [number, number, string] = [1, 2, 'three'];
// This will result in a compilation error
fixedArray = [1, 2];
fixedArray = [1, 2, 'three', 'four'];

Using ReadonlyArray

For a more immutability-oriented approach, ReadonlyArray<T> can assure array content cannot be changed after being set.

const fixedLengthArray: ReadonlyArray<number> = [1, 2, 3];
// These operations are not allowed
fixedLengthArray[0] = 10;
fixedLengthArray.push(4);

Enforcing Fixed Length at Runtime

In cases you need runtime length checking, additional programming patterns with functions and classes are your friends.

function createFixedLengthArray<T>(length: number): ReadonlyArray<T> {
    return new Proxy([], {
        set(target, property, value, receiver) {
            if (typeof property === 'number') {
                if (property >= length) {
                    throw new Error('Array length exceeded.');
                }
            }
            return Reflect.set(target, property, value, receiver);
        }
    });
}

Advanced Patterns

For advanced scenarios, you could involve more complex generics to create utility types specific for fixed-length arrays.

type FixedLengthArray<T, L extends number> = readonly T[] & { length: L };

This defines a length-typed array ensuring the TypeScript compiler will report issues if an array of incorrect length is assigned.

Conclusion

In conclusion, TypeScript provides a robust set of features for an array with fixed lengths. While tuple types offer basic fixed-size array modeling, advance scenarios might demand more sophisticated setups combining tuples, generics, and utility types to ensure runtime enforcement and complex domain modeling.