如何在单独的定义文件中扩展 TypeScript 类定义? [英] How do I extend a TypeScript class definition in a separate definition file?

查看:33
本文介绍了如何在单独的定义文件中扩展 TypeScript 类定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 Leaflet 的 JS 库,它有一个现有的 TypeScript 定义文件.

我希望使用一个插件来扩展传单中的一些对象并增加一个额外的功能.

在现有的 TypeScript 定义文件中,对象被定义为类而不是接口.

例如

声明模块 L {函数 circleMarker(latlng: LatLng, options?: PathOptions): CircleMarker;导出类 CircleMarker 扩展 Circle {构造函数(纬度:纬度,选项?:路径选项);setLatLng(latlng: LatLng): CircleMarker;setRadius(radius: number): CircleMarker;toGeoJSON(): 任何;}}

如果我尝试在单独的文件中再次定义它,则会收到关于重复标识符‘CircleMarker’"的错误.

声明模块 L {导出类 CircleMarker {bindLabel(name: string, options: any): CircleMarker;}}

这是有道理的,因为它是一个类而不是一个接口,但在这种情况下,有没有办法在不更改原始定义文件的情况下扩展这个类定义?

基本定义文件是通过 nuget 从绝对类型文件中提取的,因此我非常希望不要对其进行任何更改,因为它会使更新变得更加尴尬/容易失败.

解决方案

如果你不控制原始定义文件,也无法对其进行调整,那么不幸的是,你试图做的不是目前在 TypeScript 中受支持.TypeScript 中的 interface 是唯一允许合理扩展的构造,因为它只是编译时/语法检查而不是运行时操作.

您不能仅使用 TypeScript 使用新功能扩展 TypeScript 中的 class(并期望代码完成/智能感知按预期工作).您当然可以将这些函数添加到 CircleMarker 类的 prototype 中,但它们对 Intellisense 不可用并且将无法编译,除非您使用类型断言.>

您应该能够使用带有类型断言的 interface 而不是使用 any:

声明模块 L {导出接口 CircleMarkerEx {bindLabel(name: string, options: any): CircleMarker;}}

那么:

var cm = circle.bindLabel("name", {});

幸运的是,它没有增加任何运行时开销,只是增加了一点额外的输入(双关语!).

在 CodePlex 上有一些关于 "mix-ins" 的建议,但他们尚未实施.即使是混合建议也不是完全直接使用,并且对于不是完全用 TypeScript 编写的库也不能很好地工作(因为 JavaScript 代码太容易无法安全构建,例如混入).

I have a JS library called leaflet which has an existing TypeScript definition file.

I wish to use a plugin which extends some of the objects in leaflet with an extra function.

In the existing TypeScript definition file the objects are defined as classes rather than interfaces.

e.g.

declare module L {
    function circleMarker(latlng: LatLng, options?: PathOptions): CircleMarker;

    export class CircleMarker extends Circle {
        constructor(latlng: LatLng, options?: PathOptions);
        setLatLng(latlng: LatLng): CircleMarker;
        setRadius(radius: number): CircleMarker;
        toGeoJSON(): any;
    }
}

If I try and define it a second time in a separate file then I get an error about "Duplicate Identifier 'CircleMarker'.".

declare module L {
    export class CircleMarker {
        bindLabel(name: string, options: any): CircleMarker;
    }
}

This makes sense as it's a class and not an interface, but that being the case is there a way to extend this class definition without changing the original definition file?

The base definition file is pulled in from DefinitelyTyped via nuget so I have a very strong desire not to make any changes to it as it'll make updating much more awkward/prone to failure.

解决方案

If you don't control the original definition file, and can't make adjustments to it, then unfortunately, what you're trying to do isn't supported currently in TypeScript. An interface in TypeScript is the only construct that allows reasonable extensions as it is only a compile-time/syntax check and not a run-time operation.

You cannot extend a class in TypeScript with new functionality using only TypeScript (and expecting code-completion/Intellisense to work as expected). You could of course add the functions to the prototype for the CircleMarker class, but they would be unavailable to Intellisense and would fail to compile unless you use a type assertion.

Instead of using any, you should be able to use an interface with the type assertion:

declare module L {
    export interface CircleMarkerEx {
        bindLabel(name: string, options: any): CircleMarker;
    }
}

Then:

var cm = <L.CircleMakerEx> circle.bindLabel("name", {});

Thankfully, it doesn't add any run-time overhead, just a bit of extra typing (pun intended!).

There have been suggestions for things like "mix-ins" on CodePlex, but they have not been implemented. Even the mix-in suggestions would not be entirely straightforward to use, and wouldn't work well for libraries that weren't entirely written in TypeScript (as it would be too easy to have JavaScript code that simply could not be safely constructed for example with a mix-in).

这篇关于如何在单独的定义文件中扩展 TypeScript 类定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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