I'm trying to convert a simple Javascript prototype written in a single .html file with embedded <script>
tags to a module compiled with Typescript.
It's using Leaflet which I was happily able to get installed via
npm install leaflet
npm install --save @types/leaflet
importing via
import * as L from 'leaflet';
and using via eg.
var map = L.map('map').setView([-43.4175044, 172.185657], 8);
However I also want to use this https://rawgit.com/jieter/Leaflet.encoded/master/Polyline.encoded.js Javascript file which provides some extensions to the main Leaflet L object.
I've tried importing this via
import 'https://rawgit.com/jieter/Leaflet.encoded/master/Polyline.encoded.js'
However when I attempt to use it eg.
var coordinates = L.Polyline.fromEncoded(encoded).getLatLngs();
I get the following error:
error TS2339: Property 'fromEncoded' does not exist on type 'typeof Polyline'.
How can I get this working? Is it just a matter of providing types support for these extensions? If so, how can I do that?
It's tricky due to how polyline-encoded works: this plugin extends Leaflet
. So if we want it to work exactly as in JavaScript, we need to extend the leaflet types and its 1550 lines! Even more problematic, every time we want to update Leaflet
, we need to check whether its types have been updated and merge them with the polyline-encoded
types!
Another potential issue: in your code, Leaflet
is used in a ES6 module but polyline-encoded
is based on an IIFE that changes the current Leaflet
object L
, mixing old and new JavaScript ways. I'm curious to know if it works.
Anyway, a safer option that I see (but didn't test yet):
Leaflet.encoded.d.ts
below, to add to your project.L
as the extended type defined in Leaflet.encoded.d.ts
: Lx.L;
.Lx
instead of L
for every use of the polyline-encoded
extensions.Your code adapted:
import * as L from 'leaflet';
import 'https://rawgit.com/jieter/Leaflet.encoded/master/Polyline.encoded.js';
const Lx = L as any as Lx.L;
const map = L.map('map').setView([-43.4175044, 172.185657], 8);
const coordinates = Lx.Polyline.fromEncoded('...').getLatLngs();
Leaflet.encoded.d.ts
:
// Type definitions for Leaflet polyline-encoded 0.0.8
// Project: https://github.com/jieter/Leaflet.encoded
// Definitions by: Romain Deneau <https://github.com/rdeneau>
// TypeScript Version: 2.5
import * as Leaflet from 'leaflet';
export as namespace Lx;
export interface L {
PolylineUtil: PolylineUtil;
Polyline: Polyline;
Polygon: Polygon;
}
// -- PolylineUtil plugin ---------------------------------
export interface PolylineUtilOptions {
precision: number;
factor: number;
dimension: number;
}
export type LatLngTuple = [number, number];
export interface PolylineUtil {
/**
* Decode the string `encoded` to an array of `[lat, lng]`-arrays.
*/
decode(encoded: string, options?: number|PolylineUtilOptions): LatLngTuple[];
/**
* Encode an array of `L.LatLng` objects, or an array of arrays.
*/
encode(points: Leaflet.LatLng[]|LatLngTuple[], options?: number|PolylineUtilOptions): string;
}
// -- Polyline/Polygon extensions -------------------------
export class Polyline extends Leaflet.Polyline {
/**
* Return an encoded string for the current Polyline.
*/
encodePath(): string;
/**
* Construct a new `L.Polyline` from a string, with optional `options` object.
* Backslashes in strings should be properly escaped.
*/
fromEncoded(encoded: string, options?: Leaflet.PolylineOptions): Leaflet.Polyline;
}
export class Polygon extends Leaflet.Polygon {
/**
* Return an encoded string for the current Polygon.
*/
encodePath(): string;
/**
* Construct a new `L.Polygon` from a string, with optional `options` object.
* Backslashes in strings should be properly escaped.
*/
fromEncoded(encoded: string, options?: Leaflet.PolylineOptions): Leaflet.Polygon;
}
If it's working, this types can even be shared, submitting them to the DefinitelyTyped repository.