Typed Array Lengths in TypeScript
TypeScript offers powerful static typing that can help catch errors at compile time. This challenge focuses on leveraging TypeScript's features to create a type that represents an array of a specific, fixed length. This is useful for scenarios where you know an array should always contain a certain number of elements, such as fixed-size configuration objects or tuples where the order and number of elements are critical.
Problem Description
Your task is to define a TypeScript type, let's call it FixedLengthArray<T, N>, that generates a type representing an array of type T with a precisely defined length N.
Key Requirements:
- The type
FixedLengthArray<T, N>should accept two type arguments:T: The type of the elements within the array.N: A numeric literal type representing the exact desired length of the array.
- When a variable is typed using
FixedLengthArray<T, N>, TypeScript should enforce that the array has exactlyNelements. - Assignments to variables typed with
FixedLengthArray<T, N>should be validated. - The type should allow for common array operations (like accessing elements by index) while respecting the fixed length constraint.
Expected Behavior:
- Assigning an array with the correct length and element types to a variable of type
FixedLengthArray<T, N>should be valid. - Assigning an array with an incorrect length (more or fewer elements than
N) should result in a TypeScript compile-time error. - Assigning an array with elements of the wrong type should also result in a TypeScript compile-time error.
Edge Cases:
- Consider how the type behaves with
N = 0. - Consider how the type behaves with different element types
T.
Examples
Example 1:
// Define the type (your solution will go here)
// type FixedLengthArray<T, N extends number> = ...
type MyArrayType = FixedLengthArray<string, 3>;
const validArray: MyArrayType = ["hello", "world", "typescript"]; // This should be valid
const invalidLengthArray1: MyArrayType = ["hello", "world"]; // This should be a compile-time error
const invalidLengthArray2: MyArrayType = ["hello", "world", "typescript", "!"]; // This should be a compile-time error
const invalidElementType: MyArrayType = ["hello", 123, "typescript"]; // This should be a compile-time error
Explanation:
MyArrayType is intended to represent an array of strings with a length of exactly 3. The first assignment is valid because it meets these criteria. The subsequent assignments fail because they either have too few, too many, or incorrect element types.
Example 2:
// Assuming FixedLengthArray is defined as above
type ConfigArray = FixedLengthArray<number, 5>;
const validConfig: ConfigArray = [10, 20, 30, 40, 50]; // Valid
const invalidConfig: ConfigArray = [10, 20, 30]; // Compile-time error: missing elements
Explanation:
ConfigArray enforces an array of 5 numbers. The validConfig is accepted, while invalidConfig fails due to its insufficient length.
Example 3: Zero Length Array
// Assuming FixedLengthArray is defined as above
type EmptyArray = FixedLengthArray<boolean, 0>;
const emptyValid: EmptyArray = []; // Valid
// const emptyInvalid: EmptyArray = [true]; // Compile-time error: unexpected element
Explanation:
The type correctly handles a fixed length of zero, allowing only an empty array.
Constraints
- The solution must be a TypeScript type definition.
- The type must utilize conditional types, indexed access types, or other advanced TypeScript type features.
- The
Nparameter must be a numeric literal type (e.g.,3,5,0). The type should not be generic over a runtime number. - The type definition should be efficient and not lead to excessive compile times.
Notes
- Think about how TypeScript represents arrays and tuples. Tuples are a good starting point, but they are variadic by default. You need a way to enforce a fixed length.
- Consider using
extends numberfor theNtype parameter to ensure it's a numeric literal. - The goal is to achieve this purely at the type level, meaning the checks happen during compilation, not at runtime.