diff --git a/packages/turf-helpers/README.md b/packages/turf-helpers/README.md index fbef66c30..aac4279bc 100644 --- a/packages/turf-helpers/README.md +++ b/packages/turf-helpers/README.md @@ -96,6 +96,12 @@ var feature = turf.feature(geometry); Returns **[Feature][7]<[GeometryObject][9], [GeoJsonProperties][7]>** a GeoJSON Feature +## GeometryType + +The GeoJSON geometry types that [geometry][17] can create. + +Type: (`"Point"` | `"LineString"` | `"Polygon"` | `"MultiPoint"` | `"MultiLineString"` | `"MultiPolygon"`) + ## geometry Creates a GeoJSON [Geometry][9] from a Geometry string type & coordinates. @@ -104,7 +110,7 @@ For GeometryCollection type use `helpers.geometryCollection` ### Parameters * `type` **(`"Point"` | `"LineString"` | `"Polygon"` | `"MultiPoint"` | `"MultiLineString"` | `"MultiPolygon"`)** Geometry Type -* `coordinates` **[Array][17]\** Coordinates +* `coordinates` **CoordinatesFor\** Coordinates * `_options` **Record<[string][18], never>** (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -148,7 +154,7 @@ Creates a [Point][19] [FeatureCollection][8] from an Array of Point coordinates. ### Parameters -* `coordinates` **[Array][17]<[Position][20]>** an array of Points +* `coordinates` **[Array][21]<[Position][20]>** an array of Points * `properties` **[GeoJsonProperties][7]** Translate these properties to each Feature (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -176,7 +182,7 @@ Creates a [Polygon][5] [Feature][7] from an Array of LinearRings. ### Parameters -* `coordinates` **[Array][17]<[Array][17]<[Position][20]>>** +* `coordinates` **[Array][21]<[Array][21]<[Position][20]>>** * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -199,7 +205,7 @@ Creates a [Polygon][5] [FeatureCollection][8] from an Array of Polygon coordinat ### Parameters -* `coordinates` **[Array][17]<[Array][17]<[Array][17]<[Position][20]>>>** +* `coordinates` **[Array][21]<[Array][21]<[Array][21]<[Position][20]>>>** * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -225,7 +231,7 @@ Creates a [LineString][3] [Feature][7] from an Array of Positions. ### Parameters -* `coordinates` **[Array][17]<[Position][20]>** an array of Positions +* `coordinates` **[Array][21]<[Position][20]>** an array of Positions * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -250,7 +256,7 @@ Creates a [LineString][3] [FeatureCollection][8] from an Array of LineString coo ### Parameters -* `coordinates` **[Array][17]<[Array][17]<[Position][20]>>** +* `coordinates` **[Array][21]<[Array][21]<[Position][20]>>** * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -277,7 +283,7 @@ Takes one or more [Features][7] and creates a [FeatureCollection][8]. ### Parameters -* `features` **[Array][17]<[Feature][7]<[GeometryObject][9], [GeoJsonProperties][7]>>** input features +* `features` **[Array][21]<[Feature][7]<[GeometryObject][9], [GeoJsonProperties][7]>>** input features * `options` **[Object][15]** Optional Parameters (optional, default `{}`) * `options.bbox` **[BBox][16]?** Bounding Box Array \[west, south, east, north] associated with the Feature @@ -308,7 +314,7 @@ coordinate array. Properties can be added optionally. ### Parameters -* `coordinates` **[Array][17]<[Array][17]<[Position][20]>>** +* `coordinates` **[Array][21]<[Array][21]<[Position][20]>>** * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -323,18 +329,18 @@ var multiLine = turf.multiLineString([[[0,0],[10,10]]]); //=multiLine ``` -* Throws **[Error][21]** if no coordinates are passed +* Throws **[Error][22]** if no coordinates are passed Returns **[Feature][7]<[MultiLineString][4], [GeoJsonProperties][7]>** a MultiLineString feature ## multiPoint -Creates a [Feature][7]<[MultiPoint][22]> based on a +Creates a [Feature][7]<[MultiPoint][23]> based on a coordinate array. Properties can be added optionally. ### Parameters -* `coordinates` **[Array][17]<[Position][20]>** an array of Positions +* `coordinates` **[Array][21]<[Position][20]>** an array of Positions * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -349,9 +355,9 @@ var multiPt = turf.multiPoint([[0,0],[10,10]]); //=multiPt ``` -* Throws **[Error][21]** if no coordinates are passed +* Throws **[Error][22]** if no coordinates are passed -Returns **[Feature][7]<[MultiPoint][22], [GeoJsonProperties][7]>** a MultiPoint feature +Returns **[Feature][7]<[MultiPoint][23], [GeoJsonProperties][7]>** a MultiPoint feature ## multiPolygon @@ -360,7 +366,7 @@ coordinate array. Properties can be added optionally. ### Parameters -* `coordinates` **[Array][17]<[Array][17]<[Array][17]<[Position][20]>>>** +* `coordinates` **[Array][21]<[Array][21]<[Array][21]<[Position][20]>>>** * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -375,7 +381,7 @@ var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]); //=multiPoly ``` -* Throws **[Error][21]** if no coordinates are passed +* Throws **[Error][22]** if no coordinates are passed Returns **[Feature][7]<[MultiPolygon][6], [GeoJsonProperties][7]>** a multipolygon feature @@ -386,7 +392,7 @@ coordinate array. Properties can be added optionally. ### Parameters -* `geometries` **[Array][17]<([Point][19] | [LineString][3] | [Polygon][5] | [MultiPoint][22] | [MultiLineString][4] | [MultiPolygon][6])>** an array of GeoJSON Geometries +* `geometries` **[Array][21]<([Point][19] | [LineString][3] | [Polygon][5] | [MultiPoint][23] | [MultiLineString][4] | [MultiPolygon][6])>** an array of GeoJSON Geometries * `properties` **[GeoJsonProperties][7]** an Object of key-value pairs to add as properties (optional, default `{}`) * `options` **[Object][15]** Optional Parameters (optional, default `{}`) @@ -548,7 +554,7 @@ turf.isNumber('foo') //=false ``` -Returns **[boolean][23]** true/false +Returns **[boolean][24]** true/false ## isObject @@ -567,7 +573,7 @@ turf.isObject('foo') //=false ``` -Returns **[boolean][23]** true/false, including false for Arrays and Functions +Returns **[boolean][24]** true/false, including false for Arrays and Functions ## removeBbox @@ -577,7 +583,7 @@ This function mutates the input GeoJSON object. ### Parameters -* `geojson` **[GeoJSON][24]** GeoJSON object whose bounding boxes should be removed +* `geojson` **[GeoJSON][25]** GeoJSON object whose bounding boxes should be removed Returns **void** @@ -613,7 +619,7 @@ Returns **void** [16]: https://tools.ietf.org/html/rfc7946#section-5 -[17]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[17]: #geometry [18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String @@ -621,13 +627,15 @@ Returns **void** [20]: https://developer.mozilla.org/docs/Web/API/Position -[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error +[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array + +[22]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error -[22]: https://tools.ietf.org/html/rfc7946#section-3.1.3 +[23]: https://tools.ietf.org/html/rfc7946#section-3.1.3 -[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[24]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[24]: https://tools.ietf.org/html/rfc7946#section-3 +[25]: https://tools.ietf.org/html/rfc7946#section-3 diff --git a/packages/turf-helpers/index.ts b/packages/turf-helpers/index.ts index 9bf3aa15b..2f9f48008 100644 --- a/packages/turf-helpers/index.ts +++ b/packages/turf-helpers/index.ts @@ -225,13 +225,35 @@ export function feature< return feat; } +/** + * The GeoJSON geometry types that {@link geometry} can create. + */ +export type GeometryType = + | "Point" + | "LineString" + | "Polygon" + | "MultiPoint" + | "MultiLineString" + | "MultiPolygon"; + +// Maps a geometry type to the shape of its `coordinates` argument. +type CoordinatesFor = T extends "Point" + ? Position + : T extends "LineString" | "MultiPoint" + ? Position[] + : T extends "Polygon" | "MultiLineString" + ? Position[][] + : T extends "MultiPolygon" + ? Position[][][] + : never; + /** * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates. * For GeometryCollection type use `helpers.geometryCollection` * * @function * @param {("Point" | "LineString" | "Polygon" | "MultiPoint" | "MultiLineString" | "MultiPolygon")} type Geometry Type - * @param {Array} coordinates Coordinates + * @param {CoordinatesFor} coordinates Coordinates * @param {Object} [options={}] Optional Parameters * @returns {Geometry} a GeoJSON Geometry * @example @@ -240,38 +262,27 @@ export function feature< * var geometry = turf.geometry(type, coordinates); * // => geometry */ -export function geometry< - T extends - | "Point" - | "LineString" - | "Polygon" - | "MultiPoint" - | "MultiLineString" - | "MultiPolygon", ->( +export function geometry( type: T, - coordinates: any[], + coordinates: CoordinatesFor, _options: Record = {} ): Extract { + // `T` can't be narrowed inside the switch, so re-broaden the coordinates to + // the array shapes the constructors below accept. + const coords: any[] = coordinates; switch (type) { case "Point": - return point(coordinates).geometry as Extract; + return point(coords).geometry as Extract; case "LineString": - return lineString(coordinates).geometry as Extract; + return lineString(coords).geometry as Extract; case "Polygon": - return polygon(coordinates).geometry as Extract; + return polygon(coords).geometry as Extract; case "MultiPoint": - return multiPoint(coordinates).geometry as Extract; + return multiPoint(coords).geometry as Extract; case "MultiLineString": - return multiLineString(coordinates).geometry as Extract< - Geometry, - { type: T } - >; + return multiLineString(coords).geometry as Extract; case "MultiPolygon": - return multiPolygon(coordinates).geometry as Extract< - Geometry, - { type: T } - >; + return multiPolygon(coords).geometry as Extract; default: throw new Error(type + " is invalid"); } diff --git a/packages/turf-helpers/package.json b/packages/turf-helpers/package.json index 5d73c9afc..9d7e1e227 100644 --- a/packages/turf-helpers/package.json +++ b/packages/turf-helpers/package.json @@ -7,7 +7,8 @@ "Tom MacWright <@tmcw>", "Stefano Borghi <@stebogit>", "Denis Carriere <@DenisCarriere>", - "William Nordmann <@wnordmann>" + "William Nordmann <@wnordmann>", + "Modusensus <@modusensus>" ], "license": "MIT", "bugs": { diff --git a/packages/turf-helpers/types.ts b/packages/turf-helpers/types.ts index 4a18a4b49..3e8bb93b1 100644 --- a/packages/turf-helpers/types.ts +++ b/packages/turf-helpers/types.ts @@ -1,4 +1,13 @@ -import { BBox, GeometryCollection, LineString, Polygon, Point } from "geojson"; +import { + BBox, + GeometryCollection, + LineString, + MultiLineString, + MultiPoint, + MultiPolygon, + Polygon, + Point, +} from "geojson"; import { feature, featureCollection, @@ -200,6 +209,51 @@ const multiLineGeom = geometry( ); const multiPolyGeom = geometry("MultiPolygon", multiPoly.geometry.coordinates); +// Strict coordinates typing +const geomPoint: Point = geometry("Point", [110, 50]); +const geomLineString: LineString = geometry("LineString", [ + [110, 50], + [111, 51], +]); +const geomPolygon: Polygon = geometry("Polygon", [ + [ + [110, 50], + [111, 51], + [110, 51], + [110, 50], + ], +]); +const geomMultiPoint: MultiPoint = geometry("MultiPoint", [ + [110, 50], + [111, 51], +]); +const geomMultiLineString: MultiLineString = geometry("MultiLineString", [ + [ + [110, 50], + [111, 51], + ], +]); +const geomMultiPolygon: MultiPolygon = geometry("MultiPolygon", [ + [ + [ + [110, 50], + [111, 51], + [110, 51], + [110, 50], + ], + ], +]); +const notAPosition = [ + [110, 50], + [111, 51], +]; +// @ts-expect-error — a Point's coordinates must be a single Position +geometry("Point", notAPosition); +// @ts-expect-error — a Polygon's coordinates must be nested two levels +geometry("Polygon", [110, 50]); +// @ts-expect-error — "GeometryCollection" is not a valid type for geometry() +geometry("GeometryCollection", []); + // Custom Properties const customPt = point([10, 50], { foo: "bar" });