AlexLavoie42 / Nuxt-Mapbox

Elegant Mapbox integration with Nuxt
81 stars 11 forks source link

Type error when dynamically passing props to components #31

Closed johnghr closed 1 year ago

johnghr commented 1 year ago

I've just spun up a bare minimum implimentation and I've noticed that when I try and pass props dynamically to components (MapboxMap, MapboxSource and Mapbox layer in this case) I get ts errors. For example

Type '{ center: number[]; zoom: number; style: string; }' is not assignable to type 'MapboxComponentOptions'. Types of property 'center' are incompatible.

in the case of the MapboxMap component, and

Type '{ type: string; url: string; }' is not assignable to type 'AnySourceData'. Type '{ type: string; url: string; }' is not assignable to type 'RasterDemSource'.

in the case of MapboxSource.

Not sure if this is anticipated behaviour and the expectation is that you have to directly pass props as an object (as in your example) rather than as a var?

This is my app.vue file:

<template>
  <div id="app-container">
    <MapboxMap :map-id="mapId" :options="options">
      <MapboxSource source-id="postcode_layer" :source="source" />
    </MapboxMap>
  </div>
</template>
<script setup lang="ts">
const mapId = 'mapbox-map';
const source = {
  type: 'vector',
  url: 'mapbox://rookenthusiast.postcode_layer',
};

const options = {
  center: [-3.5275, 50.726], // starting position
  zoom: 10, // starting zoom
  style: 'mapbox://styles/mapbox/light-v11', // style URL
};
</script>
<style>
html {
  height: 100%;
  width: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  overflow: hidden;
  height: 100%;
}

#__nuxt {
  height: 100%;
}

#app-container {
  height: 100%;
  width: 100%;
  display: flex;
  justify-content: center;
  overflow: hidden;
  position: relative;
  background-color: rgb(255, 255, 255);
}
#mapbox-map {
  height: 100vh;
  width: 100vw;
}
</style>
AlexLavoie42 commented 1 year ago

The issue here is that mapbox is expecting the center array to be explicitly defined as having 2 numbers like this: [number, number] but it is being inferred that it is an array of any size (number[]).

The best way to fix this is to explicitly define your options as the type MapboxComponentOptions (I need to export this from the module in the next update). You could use MapboxOptions from the mapbox-gl module but you will get an error about missing container

The source has a similar issue, but not sure the exact cause (probably just poorly defined by mapbox). This is a similar fix by just defining the type as AnySourceData (or the proper type of source data you are using) from mapbox-gl.

Here is an example that fixes it for now:

  const mapId = 'mapbox-map';
  const source: mapboxgl.AnySourceData = {
    type: 'vector',
    url: 'mapbox://rookenthusiast.postcode_layer',
  };

  const options = {
    center: [-3.5275, 50.726] as [number, number], // starting position
    zoom: 10, // starting zoom
    style: 'mapbox://styles/mapbox/light-v11', // style URL
  };

Once I export the MapboxComponentOptions type you can use that instead.

AlexLavoie42 commented 1 year ago

MapboxComponentOptions is now exported in #32