3

I'm trying to add geoJSON into a react-map-gl map using typescript

here is my code

<Source id="my-data" type="geojson" data={data}>
    <Layer {...layerStyles}/>
</Source>

the data variable is a parsed JSON file so it is an object not

the error I get is

 Overload 1 of 2, '(props: SourceProps | Readonly<SourceProps>): Source', gave the following error.
    Type 'object' is not assignable to type 'string | Feature<Geometry, GeoJsonProperties> | FeatureCollection<Geometry, GeoJsonProperties> | undefined'.
      Type '{}' is missing the following properties from type 'FeatureCollection<Geometry, GeoJsonProperties>': type, features
  Overload 2 of 2, '(props: SourceProps, context: any): Source', gave the following error.
    Type 'object' is not assignable to type 'string | Feature<Geometry, GeoJsonProperties> | FeatureCollection<Geometry, GeoJsonProperties> | undefined'.  TS2769

    123 |             onViewportChange={(nextView:typeof viewport) => setViewport(nextView)}>
    124 |                 {/* GeoJSON */}
  > 125 |                 <Source id="my-data" type="geojson" data={data}>
        |                                                     ^
    126 |                  <Layer {...layerStyles}/>
    127 |                 </Source> 
    128 |                 {markers}

And the type of the data props in the Source component is supposed to be an object as you can see from the documentation https://visgl.github.io/react-map-gl/docs/api-reference/source

if you need any more information please ask

8
  • What is data in this context? Commented Dec 6, 2021 at 1:49
  • it's a JSON file that contained all the geoJSON I imported then parsed into an object, do it's an object containing the geoJSON Commented Dec 6, 2021 at 1:55
  • 1
    Have you verified that the shape is correct when it reaches this code? Clearly the Source component disagrees and believes that data is missing properties named type and features. Commented Dec 6, 2021 at 1:57
  • Yes, data has both a type and features I can console.log both those. Commented Dec 6, 2021 at 2:13
  • Can you share those here? Commented Dec 6, 2021 at 2:15

1 Answer 1

4

Explanation

Let's pull apart this error:

Overload 1 of 2, '(props: SourceProps | Readonly<SourceProps>): Source'
...
Overload 2 of 2, '(props: SourceProps, context: any): Source

At the top level it is showing the two possible ways that you can use the Source component. Assuming you aren't assigning it a context, let's continue looking at Overload 1

Type 'object' is not assignable to type 'string | Feature<Geometry, GeoJsonProperties> | FeatureCollection<Geometry, GeoJsonProperties> | undefined'.

This is telling us that typescript thinks data is an object, but it's expecting it to be specifically a string or a Feature or a FeatureCollection (specifically features of Geometry, GeoJsonProperties)
This tells us that object is not a specific enough type to satisfy the compiler.

Type '{}' is missing the following properties from type 'FeatureCollection<Geometry, GeoJsonProperties>': type, features

Here's it's trying to be helpful by telling us what's missing in the object type. Note that it's reduced your type to an empty object without properties.

Solution

So how do you tell the compiler what data is?
I'm going to assume that you are fetching the data and so typescript is unable to infer it's type automatically

Option 1 - use a type guard to check the incoming data

function isFeatureCollection(data: unknown): data is FeatureCollection<Geometry, GeoJsonProperties> {
    return (
        typeof data === 'object'
        && data !== null
        && 'type' in data
        && 'features' in data
    );
}

Then use the type guard to exit out of the render, and typescript will know that after this check that data will be the type expected by Source

if (!isFeatureCollection(data)) return null;

<Source id="my-data" type="geojson" data={data}>
    <Layer {...layerStyles}/>
</Source>

Option 2 - Cast the type using as to what you expect it to be:

const data = await getData() as FeatureCollection<Geometry, GeoJsonProperties>;

This isn't recommended as you're throwing away Typescript's type guarantee here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.