admin管理员组文章数量:1392050
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.
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;
}
}
Alternate approach using only interface
// 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?
Additional Info
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.
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?
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.
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;
}
}
Alternate approach using only interface
// 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?
Additional Info
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.
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?
1 Answer
Reset to default 8In the pilation process you're not getting any errors because the piler has access to the google.maps
definitions that you installed using @types
.
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.
You need to load your file only after you know that the google.maps
file has loaded successfully.
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 piler and are not being "translated" into js.
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;
}
}
}
(playground code which simulates this)
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 };
Is called Intersection Types and it means that MyType
has everything that google.maps.Marker
has plus the uuid
property.
A simple example:
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 };
本文标签: javascriptHow do you extend a class in Typescript that is loaded dynamicallyStack Overflow
版权声明:本文标题:javascript - How do you extend a class in Typescript that is loaded dynamically - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744768529a2624192.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论