如何在动态加载的Typescript中扩展一个类 [英] How do you extend a class in Typescript that is loaded dynamically
问题描述
我正在使用google地图JS API和 google.maps
命名空间,通过 npm install @ types / googlemaps
。我相信API是动态加载的,所以 google.maps
JS全局不能立即使用。
I'm using the google maps JS API together with the google.maps
namespace via npm install @types/googlemaps
. I believe the API is loaded dynamically so the google.maps
JS global is not available immediately.
但我不喜欢我明白为什么我会收到运行时错误:当我尝试扩展
google.maps.Marker $ c时,未定义的ReferenceError:google未定义
$ c>使用类
但不是界面
But I don't understand why I get the runtime error: Uncaught ReferenceError: google is not defined
when I try to extend google.maps.Marker
with a class
but not an interface
// No problem!
export interface UuidMarker extends google.maps.Marker {
uuid: string;
}
// Uncaught ReferenceError: google is not defined!!
export class UuidMarker0 extends google.maps.Marker {
uuid: string;
constructor(uuid: string, options?: gmMarkerOptions) {
super(options);
this.uuid = uuid;
}
}
仅使用界面的替代方法
// this works
export function UuidMarkerFactory(uuid: string, marker: google.maps.Marker): google.maps.Marker & {uuid:string} {
return Object.assign(marker, {uuid});
}
// this fails with google is not defined!!
export function UuidMarkerFactory0(uuid: string, options?: any): google.maps.Marker & {uuid:string} {
if (typeof google == "undefined") return null
return Object.assign(new google.maps.Marker(options), {uuid});
}
扩展动态加载的类的最佳做法是什么?
What is the best practice for extending a class that loaded dynamically?
其他信息
我正在使用 ionic2 @ RC0
使用汇总
捆绑所有模块。我的所有打字稿和 node_modules
都捆绑在一个带有源地图的 main.js
脚本中。实际的Google地图API由 angular2-google-maps
脚本加载。
I'm using ionic2@RC0
which uses rollup
to bundle all the modules. All my typescript and node_modules
are bundled into a single main.js
script with source maps. The actual google maps API is loaded by the angular2-google-maps
script.
如果我使用 interface
(似乎更多的打字稿友好)我可以用什么模式创建一个适合 UuidMarker
界面的对象?
If I extend using an interface
(which seems more typescript "friendly") what pattern can I use to create an object that fits the UuidMarker
interface?
推荐答案
在编译过程中,您没有收到任何错误,因为编译器可以访问 google .maps
使用 @types
安装的定义。
In the compilation process you're not getting any errors because the compiler has access to the google.maps
definitions that you installed using @types
.
但是,在运行时,您的文件可能在 google.maps
库加载之前被加载,因此解释器找不到 google.maps.Marker
对象。
However, in runtime your file is probably being loaded before the google.maps
library has loaded and so the interpreter can't find the google.maps.Marker
object.
您需要在知道后才能加载文件已成功加载 google.maps
文件。
You need to load your file only after you know that the google.maps
file has loaded successfully.
你没有得到 UuidMarker
接口的运行时错误,因为它在运行时不存在。
javascript中不存在接口,它们仅由typescript编译器使用,并且未被转换为js。
You don't get runtime errors for the UuidMarker
interface because it does not exist in runtime.
Interfaces don't exist in javascript, they are only used by the typescript compiler and are not being "translated" into js.
你可以通过将类定义放在函数中来做一个技巧。
这样解释器在调用这个函数之前不会执行它,这可以在google maps lib之后执行已加载:
You can do a trick by placing the class definition inside a function.
This way the interpreter won't execute it before this function is called, which can be after the google maps lib has loaded:
interface UuidMarker extends google.maps.Marker {
uuid: string;
}
let UuidMarker0: { new (uuid: string, options?: gmMarkerOptions): UuidMarker };
function classLoader() {
UuidMarker0 = class UuidMarker0 extends google.maps.Marker implements UuidMarker {
uuid: string;
constructor(uuid: string, options?: gmMarkerOptions) {
super(options);
this.uuid = uuid;
}
}
}
(游乐场代码模拟此)
另一种方法是按照你的建议放弃课程,只需这样做:
Another approach, is to drop the class as you suggested and just do:
function UuidMarker(uuid: string, marker: google.maps.Marker): google.maps.Marker & { uuid: string } {
return Object.assign(marker, { uuid });
}
编辑
此语法:
Edit
This syntax:
type MyType = google.maps.Marker & { uuid: string };
被称为交集类型,这意味着 MyType
包含 google的所有内容.maps.Marker
加上 uuid
属性。
Is called Intersection Types and it means that MyType
has everything that google.maps.Marker
has plus the uuid
property.
一个简单的例子:
interface Point {
x: number;
y: number;
}
type Point3D = Point & { z: number };
let p1: Point = { x: 0, y: 0 };
let p2: Point3D = { x: 0, y: 0, z: 0 };
这篇关于如何在动态加载的Typescript中扩展一个类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!