skip to Main Content

I wrote a simple Cartesian product implementation in Typescript, but the type inferred is not what I have expected:

export function cartesianProduct<X, Y> (a: X[], b: Y[]): Array<[X, Y]> {
    return a.flatMap(x => b.map(y => [x, y]));
}

enter image description here

As you can see, the inferred type is (X | Y)[][] instead of [X, Y][]. This seems weird to me because [x, y] should have type [X, Y] (x is of X type and y is of Y type).
Any idea why I am getting this type error and how to fix?

2

Answers


  1. Typescript is confused about your types. Your code makes it seem like you want an array which returns more arrays which have a mix of your X and Y. However, it seems you want an array of pairs which would be [X, Y].

    To fix your error, you would have to define that the inner arrays should be [X, Y].
    Like this:

    export function cartesianProduct<X, Y>(a: X[], b: Y[]): Array<[X, Y]> {
    return a.flatMap((x: X) => b.map((y: Y) => [x, y] as [X, Y]));
    

    }

    Login or Signup to reply.
  2. TypeScript generally infers array literals like [x, y] to have array types instead of tuple types. If you want to change this, you need to give the type checker context for which it to infer the type differently. There are various ways to go about this (such as a const assertion, or using a type assertion with the as operator, or by manually specifying the generic type argument to map as map<[X, Y]>).

    Currently the approach I’d most recommend is to use the satisfies operator; if you write expr satisfies Type it will tell the compiler to use Type as context for inferring expr‘s type. If it can infer a compatible type it will; otherwise it will produce an error, so the satisfies operator is type safe in a way that a type assertion is not.

    So all you need to do is this:

    function cartesianProduct<X, Y>(a: X[], b: Y[]): Array<[X, Y]> {
        return a.flatMap(x => b.map(y => [x, y] satisfies [X, Y]));
    }
    

    And it works.

    Playground link to code

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search