Skip to content

Issues modeling GeoJSON spec with rescript@11 types #6277

Closed
@cristianoc

Description

@cristianoc

Discussed in #6273

Originally posted by glennsl May 28, 2023
I've been trying to model GeoJSON using rescript@11 types, just to see if I can, and am stumbling on just a few issues that I think should be feasible (though not easy) to fix since all the necessary features do exist in various forms. So I figured I'd document this as a prominent use case.

See the full TypeScript type definitions for reference.

The big problem is that a GeoJSON document can be either a single geometry object (of which there are several kinds), a "feature" which contains geometry, or a feature collection. These all use a type tag, but because geometry objects are included in several different types, modeling this requires structural typing. And unfortunately @tag only works on nominal variants, not structural (polymorphic) ones. This is also the case with inline records, which is necessary for @tag to be useful, so that's another hurdle.

Essentially, I'd like to define the types like this:

@tag("type")
type rec geometry = [
  | #Point({coordinates: pos})
  | #MultiPoint({coordinates: array<pos>})
  | #LineString({coordinates: array<pos>})
  | #MultiLineString({coordinates: array<array<pos>>})
  | #Polygon({coordinates: array<array<pos>>})
  | #MultiPolygon({coordinates: array<array<array<pos>>>})
  | #GeometryCollection({coordinates: array<geometry>})
]

@tag("type")
type feature = [
  | #Feature({geometry: geometry})
]

@tag("type")
type t = [
  | geometry
  | feature
  | #FeatureCollection({features: array<feature>})
]

Another minor problem is that positions and bounding boxes are arrays of different arities. These could be modeled with an unboxed tagged variant containing tuples of different arities, and possibly a constructor an array to cover the remaining arities. E.g.:

@unboxed
type pos = 
  | LatLng((float, float))
  | LatLngAlt((float, float, float))
  | M(array<float>)

Lots of edge cases to consider though. A further improvement could be to (optionally) model inline records in unboxed variants as arrays, so that it could be:

@unboxed
type pos = 
  | LatLng({lat: float, lng: float})
  | LatLngAlt({lat: float, lng: float, alt: float})
  | M(array<float>)
```</div>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions