Type 'CustomMap' is missing the following properties from type 'Map<Element>'

Viewed 786

I have created a custom KmlLayer class to which I had to add in a value of the custom map class to the map property similar to this guide here:

https://developers.google.com/maps/documentation/javascript/examples/layer-kml

Like so:

import { CustomMap } from "./CustomMap";
// src: string = "http://cales-map.webitects.com/HOLC_KML.kmz";
const customMap = new CustomMap("map");

export class CustomKmlLayer {
  private kmlMap: google.maps.KmlLayer;

  // here is where I am initializing the KML Layer of the map
  constructor(src: string) {
    this.kmlMap = new google.maps.KmlLayer({
      url: src,
      map: customMap,
    });
  }

  kmlLayerMethod() {
    google.maps.event.addListener(this.kmlMap, "click", () => {
      console.log("KML Layer event clicked!");
    });
  }
}

Above I imported the CustomMap class from here:

// Instructions to every other class
// on how they can be an argument to
// 'addMarker', even though right now

import { Data } from "./Data";

// there is only one 'Data' class
export interface Mappable {
  Latitude: number;
  Longitude: number;
  markerContent(): string;
}

export class CustomMap {
  private googleMap: google.maps.Map;

  // here is where I am initializing the map to be upon boot up
  constructor(divId: string) {
    this.googleMap = new google.maps.Map(document.getElementById(divId), {
      zoom: 6,
      center: {
        lat: 36.778259,
        lng: -119.417931,
      },
      disableDefaultUI: true,
      styles: [...],
    });
  }

  // this method gets applied later inside `index.ts` when
  // user clicks on 'Oakland, CA' from dropdown
  addOakland(): void {
    const oak = (this.googleMap = new google.maps.Map(
      document.getElementById("map"),
      {
        zoom: 13,
        center: {
          lat: 37.804363,
          lng: -122.271111,
        },
        disableDefaultUI: true,
        styles: [...],
      }
    ));
  }

  // this method gets applied later inside `index.ts` when
  // user clicks on 'San Francisco, CA' from dropdown
  addSanFran(): void {
    this.googleMap = new google.maps.Map(document.getElementById("map"), {
      zoom: 13,
      center: {
        lat: 37.733795,
        lng: -122.446747,
      },
      disableDefaultUI: true,
      styles: [...],
    });
  }

  // makes the red dots happen including the listener
  // for clicking the dots and seeing their label
  addCircleMarker(mappable: Mappable): void {
    const circleMarker = new google.maps.Circle({
      strokeColor: "#FF0000",
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: "#FF0000",
      fillOpacity: 1,
      map: this.googleMap,
      clickable: true,
      center: {
        lat: mappable.Latitude,
        lng: mappable.Longitude,
      },
      radius: 120,
    });

    const infoWindow = new google.maps.InfoWindow({
      content: mappable.markerContent(),
    });

    google.maps.event.addListener(circleMarker, "click", () => {
      infoWindow.setPosition(circleMarker.getCenter());

      infoWindow.open(this.googleMap);
    });
  }
}

However, with this implementation, I get the following error:

Type 'CustomMap' is missing the following properties from type 'Map': addListener, fitBounds, getBounds, getCenter, and 31 more.ts(2740) kml.d.ts(18, 9): The expected type comes from property 'map' which is declared here on type 'KmlLayerOptions'

When I click on Map inside my CustomMap class, I see the type definition file with those properties, but those properties are now missing when I import and instantiate the CustomMap class?

I really need these to work as separate classes.

If anyone wants to try and clone the boilerplate and see if you can reproduce: https://github.com/ldco2016/mappy

I added it as a method:

addKmlLayer(): void {
    this.kmlLayer = new google.maps.KmlLayer({
      url: "http://my-maps.com/HOLC_KML.kmz",
      map: this.googleMap,
    });
  }

but nothing is displaying.

1 Answers

I believe typescript wants your CustomMap to extend google.maps.Map. But since you seem to be using composition, I guess you'll have to proxy all those methods.

new google.maps.KmlLayer({
      url: src,
      map: customMap, // customMap should implement google.maps.Map
    });

Alternatively, you could make googleMap property public (or add a getter for it) and use it during the layer instantiation:

new google.maps.KmlLayer({
      url: src,
      map: customMap.googleMap,
    });

But you'll have to re-instantiate the layer every time the value of the googleMap property changes (after adding Oakland or SanFran etc).

I hope this can help you find the right solution.

Related