Skip to content

Unable to call map on array of variable depth #35045

Closed
@danvk

Description

@danvk

I'm trying to write a function which transforms the coordinates of any type of GeoJSON geometry. The coordinates of a Geometry can be either number[] (a Point), number[][] (a LineString), number[][][] (a Polygon) or number[][][][] (a MultiPolygon). I have a recursive implementation which works but does not type check.

TypeScript Version: 3.7.2

Search Terms:

  • 2349

Code

type Position = number[];

function isNestedArray<T extends any[]>(x: T | T[]): x is T[] {
  return Array.isArray(x[0]);
}

export function transformCoordArray(
  coords: Position | Position[] | Position[][],
  fn: (pt: Position) => Position
): any[] {
  if (isNestedArray(coords)) {
    coords;  // type is Position[] | Position[][]
    return coords.map(c => transformCoordArray(c, fn));
    //            ~~~ This expression is not callable.
  } else {
    coords;  // type is Position
    return fn(coords);
  }
}

(playground)

The full error message is:

This expression is not callable.
  Each member of the union type '
   (<U>(callbackfn: (value: Position, index: number, array: Position[]) => U, thisArg?: any) => U[])
 | (<U>(callbackfn: (value: Position[], index: number, array: Position[][]) => U, thisArg?: any) => U[])
' has signatures, but none of those signatures are compatible with each other.(2349)

The call is valid because c's type should be Position | Position[], which is assignable to Position | Position[] | Position[][].

Interestingly, I can make the error go away by assigning to a new variable which has a broader type ((Position | Position[])[]):
(playground)

export function transformCoordArray(
  coords: Position | Position[] | Position[][],
  fn: (pt: Position) => Position
): any[] {
  if (isNestedArray(coords)) {
    coords;  // type is Position[] | Position[][]
    const c2: (Position | Position[])[] = coords;
    return c2.map(c => transformCoordArray(c, fn));  // ok
  } else {
    coords;  // type is Position
    return fn(coords);
  }
}

Expected behavior:

No error.

Actual behavior:

The given error.

Playground Link: playground

Related Issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions