16

I'm using the mapbox-gl library with TypeScript, and I've installed its community sourced type definitions with @types/mapbox-gl. When I try to import and set an accessToken to use the library, my TypeScript compiler throws this error: TS2540: Cannot assign to 'accessToken' because it is a constant or a read-only property.

So I pulled up the .d.ts file and the variable in question looks extremely assignable (seen here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/mapbox-gl/index.d.ts):

declare namespace mapboxgl {
   let accessToken: string;
   ...

This is my code:

import * as mapbox from 'mapbox-gl';
mapbox.accessToken = 'token';

Versions!

"@types/mapbox-gl": "^0.35.0",
"typescript": "^2.3.4",
"mapbox-gl": "^0.37.0",

TypeScript hackery says that I can cast mapbox to any and it will work, but I'm very curious what about the typing is going wrong here.

kyleburke
  • 269
  • 4
  • 8

3 Answers3

39

Here's a temporary workaround I've been using:

Object.getOwnPropertyDescriptor(mapboxgl, "accessToken").set('YOUR_TOKEN');

Explanation

Since the object was redefined to use a custom setter which places the token inside an internal closure - we can call the setter function directly as shown in the example.

Diving a little deeper, we can see that es6 modules are constants by definition: https://github.com/Microsoft/TypeScript/issues/6751#issuecomment-177114001

we can then do something like: (mapboxgl as any).accessToken = ... which will work.

silicakes
  • 6,364
  • 3
  • 28
  • 39
  • (mapboxgl as any).accessToken = ... <---doesn't work either, Object.getOwnPropertyDescriptor(mapboxgl, "accessToken").set('YOUR_TOKEN'); <-- works fine. – Anton Pilyak Feb 14 '19 at 12:37
23

For those finding this now ... You don't even need to set the Mapbox accessToken this way, it can be passed in as an option (since v1.2)

const map = new mapboxgl.Map({
  accessToken: '...',
  container: '...',
  style: '...',
});

Pity it's not the method used in any of the examples (yet).

Docs: https://docs.mapbox.com/mapbox-gl-js/api/#map

1.2 release notes: https://github.com/mapbox/mapbox-gl-js/releases/tag/v1.2.0

PR that adds it: https://github.com/mapbox/mapbox-gl-js/pull/8364

David Gilbertson
  • 4,219
  • 1
  • 26
  • 32
  • I'm using a helper function based on this to inject a default token: `import { Map as MapboxMap, MapboxOptions } from 'mapbox-gl'; export const createMap = (config: MapboxOptions): MapboxMap => new MapboxMap({ accessToken: MAPBOX_ACCESS_TOKEN, ...config })` – charles-allen Nov 07 '21 at 13:26
4

You can also use this format:

(mapboxgl as typeof mapboxgl).accessToken = ...
AP inc.
  • 156
  • 11