Typescript ReferenceError: google is not defined, but only in standalone files

Typescript ReferenceError: google is not defined, but only in standalone files

我正在构建一个带有嵌入式 Google 地图的 React 应用程序。

我有一个自定义菜单元素,我想在点击后在地图上显示它。 Google's docs instruct me 到 'implement'(虽然我认为在 Typescript 术语中,它们的意思是 extendgoogle.maps.OverlayView class 以便在地图上渲染元素。

当我定义 class ContextMenu extends google.maps.OverlayView class inline 时,代码编译正常并且我的元素出现了点击。我想使用 Typescript 在单独的文件中定义此 class。

但是,当我将 ContextMenu 移动到一个单独的文件时,React 出错并显示 ReferenceError: google is not defined

知道如何 'import the namespace' 使 ContextMenu.ts 知道 google 在哪里吗?似乎我在这里遗漏了一些关于 Typescript 的基本知识,但是我能够找到的 none 他们的文档讨论了使用外部名称空间创建 classes 的做法。

或者 extends 这样做的方法不对吗?我是否应该遵循 Google 的说明,即使是在 Typescript 中,它的存在是为了避免弄乱原型

Inherit from this class by setting your overlay's prototype: MyOverlay.prototype = new google.maps.OverlayView();.


工作代码:

// App.tsx
import React from 'react'
import { Wrapper } from '@googlemaps/react-wrapper'
// cannot define ContextMenu here

const App: React.VFC = () => {
  // cannot define ContextMenu here
  const onClick = (e: google.maps.MapMouseEvent) => {
    // CAN define ContextMenu here
    class ContextMenu extends google.maps.OverlayView {
      private origin_: google.maps.LatLng
      constructor(origin: google.maps.LatLng) {
        super()

        this.origin_ = origin
      }
    }

    const menu =  new ContextMenu(e.latLng)
  }

  return (
    <Wrapper ...>
    // Map goes here
    </Wrapper>
  )
}


损坏的代码:

// App.tsx as above, without ContextMenu defined.

// ContextMenu.ts
class ContextMenu extends google.maps.OverlayView {
  // ...
}

不可能直接扩展 google.maps.* class 因为它实际上不可用(这可能取决于 tsconfig 目标,但我还没有测试过)。您可以在 TypeScript 中使用以下模式来延迟。

export interface OverlayViewSafe extends google.maps.OverlayView {}

/**
 * Extends an object's prototype by another's.
 *
 * @param type1 The Type to be extended.
 * @param type2 The Type to extend with.
 * @ignore
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function extend(type1: any, type2: any): void {
  // eslint-disable-next-line prefer-const
  for (let property in type2.prototype) {
    type1.prototype[property] = type2.prototype[property];
  }
}

/**
 * @ignore
 */
export class OverlayViewSafe {
  constructor() {
    // We use the extend function for google.maps.OverlayView
    // because it might not always be available when the code is defined.
    extend(OverlayViewSafe, google.maps.OverlayView);
  }
}