Home > Back-end >  How can I ensure an array is passed a certain number of parameter in a function apart from using a t
How can I ensure an array is passed a certain number of parameter in a function apart from using a t

Time:11-09

How can I ensure an array is passed a certain number of parameter in a function apart from using a tuple

I have a function in typescript which takes an array as a parameter and when the function is called i want a certain number of elements to be passed in the array how can I achieve this apart from using a tuple

type a =(arr: [number, number]) => boolean
const b:a = (arr) => {}
b([]) // should throw an error if the parameter passed in array is less than two

How can I achieve this without using tuples

CodePudding user response:

You could extend Array<number> with a specific length and types for each index:

interface TupleOfTwoNumbers extends Array<number> {
    length: 2;
    0: number;
    1: number;
}

type a = (arr: TupleOfTwoNumbers) => boolean

const b: a = (arr) => true

b([]);        // !
b([1]);       // !
b([1, 2]);    // ok
b([1, 2, 3]); // !

but the errors generated aren't as helpful:

Argument of type '[]' is not assignable to parameter of type 'TupleOfTwoNumbers'.(2345)

compared to using tuples:

Argument of type '[]' is not assignable to parameter of type '[number, number]'. Source has 0 element(s) but target requires 2.(2345)

Playground

CodePudding user response:

If you have to do this instead of using tuples, you can type the length property of the array as the length you want, and then it will require the length of the passed array to match that.

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

function foo(arr: FixedLengthArray<number, 3>) {
  // Do stuff
}

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 as const is required to make the length of the array fixed instead of just plain number. This reflects reality, as a regular array's length can change and therefore type-checking should fail unless it is definitely a certain length.

You can use either as const or assert the type of the array:

// 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>)
  • Related