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 术语中,它们的意思是 extend) google.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);
}
}
我正在构建一个带有嵌入式 Google 地图的 React 应用程序。
我有一个自定义菜单元素,我想在点击后在地图上显示它。 Google's docs instruct me 到 'implement'(虽然我认为在 Typescript 术语中,它们的意思是 extend) google.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);
}
}