Dealing with Mapbox hidden symbols (3. Augmenting types)
2022-09-24
I have been working on a utility library for Mapbox GL JS, that deals with symbols hidden by another symbol on the screen. This is the third blog post of the series that will walk you through the development of the library.
Background
In the last two blog posts of this series, I showed,
- How to recalculate collision boxes of symbols
- How to associate symbol features with recalculated collision boxes
In this blog post, we tackle a remaining issue that some types in Mapbox GL JS (mapbox-gl-js
) were not available for TypeScript.
The library (mapbox-collision-boxes
) is available on my GitHub repository.
TypeScript?
TypeScript is a variant of JavaScript, which provides powerful typing features.
Please refer to the official website of TypeScript for more details.
This page[1] can help understand the difference between TypeScript and JavaScript.
I have chosen TypeScript for the implementation language of mapbox-collision-boxes
.
Is mapbox-gl-js typed?
Yes, but mapbox-gl-js
is typed with Flow which is another flavor of JavaScript for typing.
Unfortunately, type definitions on Flow are not compatible with TypeScript.
So we need external type definitions of mapbox-gl-js
for TypeScript.
Thanks to the hard work of contributors from the TypeScript community, these types are available as @types/mapbox-gl
*.
* The latest version of @types/mapbox-gl
was 2.7.5 when I was writing this blog post, and it was based on mapbox-gl-js
version 2.7 while the then latest version was 2.10.
However, I have not faced any issues related to the version difference so far.
What @types/mapbox-gl missing
@types/mapbox-gl
does not expose some properties and types on which mapbox-collision-boxes
depends.
For instance, the class Map
(@types/mapbox-gl/index.d.ts#L201-L602) omits the property style: Style
.
@types/mapbox-gl
neither defines the class Bucket
nor SymbolBucket
.
How can we circumvent it?
One may be inclined to give up type checks, but this should be a last resort.
We can use module augmentation to enhance existing type definitions of mapbox-gl-js
.
"Module augmentation" is a slightly advanced TypeScript feature.
Please refer to the TypeScript documentation for more details.
For instance, the following snippet adds the property style: Style
to the class Map
:
;
After the above declaration, you can access Map#style
in a type-safe manner.
For Bucket
and SymbolBucket
, we can just add interfaces for them since they are simply missing in @types/mapbox-gl
:
I also have introduced a utility function that tests if a given Bucket
is a SymbolBucket
(mapbox-collision-boxes/private/mapbox-types.ts#L232-L234), which uses another TypeScript feature "type predicates".
You can find minimum definitions necessary to implement mapbox-collision-boxes
on my GitHub repository.
Wrap-up
In this short blog post, I have shown how to extend existing types in mapbox-gl-js
(@types/mapbox-gl
) while introducing the following TypeScript features,
mapbox-collision-boxes
is available on my GitHub repository.