Kludge
Kludge

Reputation: 29

Need help defining correct types from react-leaflet for typescript

I have a 'first' project trying to use react-scripts-ts and react-leaflet.

I am trying to create the following class which seems like ti should be straight forward:

import {map, TileLayer, Popup, Marker } from 'react-leaflet';
class LeafletMap extends React.Component {
  constructor () {
    super();
    this.state = {
      lat: 51.505,
      lng: -.09,
      zoom: 13
    };
  }

render() {
    const position = [ this.state.lat, this.state.lng];
    return (
      <Map center={position} zoom={this.state.zoom}>
        <TileLayer
          url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
          attribution="&copy; <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors"
        />
        <Marker position={position}>
          <Popup>
            <span>A pretty CSS3 popup.<br/>Easily customizable.</span>
          </Popup>
        </Marker>
      </Map>
    );
  }
}

The error I am getting amounts to

Property 'lat' does not exist on type 'Readonly<{}>'

on assignment of lat and lng to position (TS2339) and similarly

Type 'any[]' is not assignable to type '[number, number] | LatLng | LatLngLiteral | undefined'.

On assigning position to center (TS2322).

From what I can tell this is/was connected to the typescript version but I believe I have a new enough version this should not be the case.

package.json:

{
  "name": "map-experiment",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@types/geojson": "^1.0.4",
    "@types/leaflet": "^1.2.0",
    "@types/react-leaflet": "^1.1.4",
    "leaflet": "^1.2.0",
    "prop-types": "^15.6.0",
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "react-leaflet": "^1.7.0",
    "react-scripts-ts": "2.7.0"
  },
  "scripts": {
    "start": "react-scripts-ts start",
    "build": "react-scripts-ts build",
    "test": "react-scripts-ts test --env=jsdom",
    "eject": "react-scripts-ts eject"
  },
  "devDependencies": {
    "@types/jest": "^21.1.2",
    "@types/node": "^8.0.33",
    "@types/react": "^16.0.10",
    "@types/react-dom": "^16.0.1"
  }
}

I nave tried defining position as [Number, Number], should I be giving it a different type annotation?

Proof of concept without typescript can be found here

Upvotes: 2

Views: 4428

Answers (3)

dkocich
dkocich

Reputation: 221

I added @types/react-leaflet to my project to get type definitions for LatLng but const position: [number, number] = [this.state.lat, this.state.lng]; was enough also.

Upvotes: 1

Pasi
Pasi

Reputation: 2674

You're not specifying the type of your state. Try this:

class LeafletMap extends React.Component<{}, {lat: number, lng: number, zoom: number}> {

Even after this, there's an additional complication. The type inferred by TypeScript for the position:

const position = [ this.state.lat, this.state.lng ];

...is number[] (any array of numbers), which is different type than [number, number] (an array with exactly two numbers). You can solve this by giving the type:

const position: [number, number] = [ this.state.lat, this.state.lng ];

Or using the other form accepted by Leaflet:

const position = {lat: this.state.lat, lng: this.state.lng };

Upvotes: 4

lankovova
lankovova

Reputation: 1426

You should always call super method in your constructor with props as attribute. Check out my changes to your code.

class LeafletMap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      lat: 51.505,
      lng: -.09,
      zoom: 13
    };
  }
  ...
}

Upvotes: 0

Related Questions