user4704976
user4704976

Reputation:

How to enforce tuple length on all function parameters that use the same generic tuple type?

It makes sense that [number, number] | [number] extends [number, ...number[]], but I'm wondering if there's a way to enforce the tuple length based on the first parameter so that the second tuple must use that same length.

function addVectors<T extends [number, ...number[]]>(v1: T, v2: T) {
  // not implemented
}

// T becomes [number].
addVectors([1], [2]);

// T becomes [number, number] | [number].
addVectors([1, 3], [3]);

I want to prevent this from compiling:

addVectors([1, 3], [3]);

Is it possible to achieve that in TypeScript?

Upvotes: 1

Views: 188

Answers (1)

user4704976
user4704976

Reputation:

I got it to work by creating a second type parameter which extends the first:

function addVectors<T extends [number, ...number[]], U extends T>(v1: T, v2: U) {
  // not implemented
}

// T becomes [number].
addVectors([1], [2]);

// Does not compile.
// "Argument of type '[number]' is not assignable to parameter of type '[number, number]'".
addVectors([1, 3], [3]);

I took it a step further and made addVectors accept two or more vectors of the same dimension:

function addVectors<T extends [number, ...number[]], U extends T>(...vectors: [T, U, ...U[]]) {
  // not implemented
}

addVectors([1], [2]);

addVectors([1, 1], [2, 2], [3, 3]);

// Does not compile.
addVectors([1, 1], [2, 2], [3, 3], [4, 4, 4]);

Upvotes: 0

Related Questions