&引用;建造商;在typescript接口中

&引用;建造商;在typescript接口中,typescript,Typescript,我从正在使用的库中收到以下界面: export interface LatLng { constructor(lat: number, lng: number): void; lat(): number; lng(): number; } 如何创建此类的实现?(我需要一个测试模拟)一个外观自然的实现,构造函数定义为: export class LatLngImpl implements LatLng { constructor(private _lat: number, pri

我从正在使用的库中收到以下界面:

export interface LatLng {
  constructor(lat: number, lng: number): void;
  lat(): number;
  lng(): number;
}
如何创建此类的实现?(我需要一个测试模拟)一个外观自然的实现,构造函数定义为:

export class LatLngImpl implements LatLng {
  constructor(private _lat: number, private _lng: number) {  }
不编译:

类“LatLngImpl”不正确地实现了接口“LatLng”。 属性“构造函数”的类型不兼容。 类型“功能”不可分配给类型“(纬度:编号,液化天然气:编号)=>>void”。 类型“Function”不提供与签名匹配的内容(lat:number,lng:>number):void'

我在typescript中读到了constructor接口,但我认为它在这里不适用

编辑:


我不理解的是接口中的
constructor()
声明。带有构造函数签名的接口使用
new()
语法。

我认为不能将构造函数放入接口中

interface IPerson 
{
    firstName: string;
    lastName: string;
}

class Person implements IPerson 
{
    constructor (public firstName: string, public lastName: string) 
    {
        //TODO
    }
}

var personA: IPerson = new Person('Jane', 'Smith');
var personB: IPerson = { firstName: 'Jo', lastName: 'Smith' };

从技术上讲,构造函数是一种特殊的静态函数调用,它返回自身的实例,因此它作为接口的一部分实际上没有意义,因为接口成员是实例绑定的

Typescript有一点编译器技巧使它们静态绑定,并将其用于环境声明

在您的情况下,要提供实现,您需要从接口中删除构造函数:

interface LatLng {
    lat(): number;
    lng(): number;
}

class LatLngImpl implements LatLng {
    constructor(lat: number, lng: number) {

    }

    lat(): number {
        return 0;
    }

    lng(): number {
        return 0;
    }
}
如果
LatLng
在其他地方实现,则只需提供环境声明:

interface LatLng {
    lat(): number;
    lng(): number;
}

interface LatLngConstructor {
    new(lat: number, lng: number): LatLng;
}

declare var LatLng: LatLngConstructor;

请注意,
LatLngConstructor
定义了一个
new(…):LatLng
,它描述了构造函数签名。

这个库来自哪里?不管是谁写的,都应该受到严厉的批评。要么是一个错误(在这种情况下,他们从未测试过它),要么是故意的,但很卑鄙:使用
构造函数作为实例方法的标识符只是自找麻烦

编辑2019-04-25:麻烦不仅仅是“这是个坏主意”;实际上,它看起来像是一旦JavaScript本机支持类字段。TypeScript将更改以在3.5+版本中反映这一点,因此下面的实现将停止工作。有关更多信息,请参阅最近打开的GitHub问题。在TS3.5之后,似乎没有办法让一个类的实例
构造函数
属性本身不是实际的构造函数

要么库作者打算引用您使用
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;
  }
}
诀窍是使用字符串literal
“constructor”
而不是裸词
constructor
。从:

字符串文字可用于提供无效标识符的属性名称

通过使用字符串文字,我们能够将其声明为实例方法,而不是在调用
new
时调用的静态类构造函数方法,并且它可以顺利编译

现在我们可以使用它,如果我们敢:

const latLng=new LatLngImpl();

建造商(47.6391132,-122.1284311);//更正式地说,一个实现接口的类是一个关于该类实例拥有什么的契约。由于类的实例不包含构造签名,因此它不能满足接口要求Ryan Cavanaugh是的,我理解'new():MyInterface'的工作原理。但在该库中,它被声明为“constructor():void”。我怀疑这是某种错误。接口中的声明将其视为一个普通函数,而在类中,构造函数是一个保留字。重要的是,
接口
是关于确保创建什么,而不是它是如何到达那里的。根据我的经验,强迫构造器以某种方式运行只会带来更多的痛苦,而没有任何实际的好处。i、 例如,任何正在消费的
LatLngImpl
都只关心
lat
lng
属性,而构造函数细节应该是无关的。任何更严格的要求都可能是错误代码的标志。