我从正在使用的库中收到以下界面:
export interface LatLng {
constructor(lat: number, lng: number): void;
lat(): number;
lng(): number;
}
Run Code Online (Sandbox Code Playgroud)
如何创建此类的实现?(我需要一个测试模型)一个自然的实现,其构造函数定义为:
export class LatLngImpl implements LatLng {
constructor(private _lat: number, private _lng: number) { }
Run Code Online (Sandbox Code Playgroud)
无法编译:
类“ LatLngImpl”错误地实现了接口“ LatLng”。属性“构造函数”的类型不兼容。类型“功能”不能分配给类型“(纬度:数字,lng:数字)=>>无效”。类型'Function'不提供签名'(lat:number,lng:> number):void'的匹配项
我读过有关打字稿中的构造函数接口的信息,但我认为它不适用于此处。
编辑:
我不需要理解的是constructor()接口中的此声明。具有构造函数签名的接口使用new ()语法。
从技术上讲,构造函数是一个特殊的静态函数调用,它返回自身的实例,因此将其作为接口的一部分并没有任何意义,因为接口成员是实例绑定的。
Typescript具有一些使它们静态绑定的编译器技巧,并将其用于环境声明。
对于您的情况,要提供实现,您需要从接口中删除构造函数:
interface LatLng {
lat(): number;
lng(): number;
}
class LatLngImpl implements LatLng {
constructor(lat: number, lng: number) {
}
lat(): number {
return 0;
}
lng(): number {
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
如果LatLng在其他地方实现,则只需提供一个环境声明:
interface LatLng {
lat(): number;
lng(): number;
}
interface LatLngConstructor {
new(lat: number, lng: number): LatLng;
}
declare var LatLng: LatLngConstructor;
Run Code Online (Sandbox Code Playgroud)
请注意,LatLngConstructor定义了一个new(...): LatLng,它描述了构造函数签名。
这个图书馆是哪里来的?无论是谁写的,都应该严肃地与他交谈。这是一个错误(在这种情况下,他们从未进行过测试),或者是有意的,但eeeeevil:使用不完全保留的单词 constructor作为实例方法的标识符只是在自找麻烦。
编辑2019-04-25:麻烦比“这是一个坏主意”还要糟糕;实际上,一旦JavaScript原生支持类字段,拥有一个名为属性的类将是一个错误"constructor"。TypeScript将进行更改以在版本3.5+中反映出来,因此下面的实现将停止工作。有关更多信息,请参见最近打开的GitHub问题Microsoft / TypeScript#31020。在TS3.5之后,似乎将无法拥有一个实例constructor属性而不是实际构造函数本身的类。
要么库作者想引用一个真正的构造函数,然后调用new@ Series0ne的建议;或作者真的想使用实例方法来初始化对象,在这种情况下,他们应该帮大家一个忙,并使用更传统的方法名称,例如init()。
在任何一种情况下,没有人应该接受您得到的接口,当然也没有人应该实现它。
让我们实现它:
export class LatLngImpl implements LatLng {
private _lat: number;
private _lng: number;
lat() {
return this._lat;
}
lng() {
return this._lng;
}
// here's the important part, but see Microsoft/TypeScript#31020
"constructor"(lat: number, lng: number) {
this._lat = lat;
this._lng = lng;
}
}
Run Code Online (Sandbox Code Playgroud)
诀窍是使用字符串文字"constructor"而不是裸字constructor。根据TypeScript规范:
字符串文字可能会用于提供无效标识符的属性名称
通过使用字符串文字,我们能够将其声明为实例方法,而不是在调用时调用的静态类构造方法new,并将其声明为愉快地编译。
如果我们敢,现在就可以使用它:
const latLng = new LatLngImpl();
latLng.constructor(47.6391132, -122.1284311); // Why not init()?
console.log("Latitude: " + latLng.lat() + ", Longitude: " + latLng.lng());
Run Code Online (Sandbox Code Playgroud)
,我们不应该胆子大。
再次编辑2019-04-25上面的带引号的字符串实现从TypeScript 3.5开始将不起作用,正确的答案是“您不能这样做”和“使用真实的构造函数”。
希望能有所帮助;祝好运!
| 归档时间: |
|
| 查看次数: |
15076 次 |
| 最近记录: |