如何在动态加载的Typescript中扩展一个类 [英] How do you extend a class in Typescript that is loaded dynamically

查看:86
本文介绍了如何在动态加载的Typescript中扩展一个类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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>使用但不是界面

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆