2017-10-18 208 views
0

功能接口我想要一类的行为像JS日期功能:打字稿:与构造

  1. 当通过new称它创建类的实例。
  2. 当作为一个函数被调用时,它会做一些静态的东西。

我该如何实现这个接口?

interface A { 
    (): string; 
    new(arg: number); 
    GetValue(): number; 
} 

当前的解决方案无法编译,但产生正确的JS代码在操场:

class B implements A { 

    private Value: number; 

    constructor(arg: number) { 
     if (this.constructor == B) { 
      this.Value = arg; 
     } else { 
      return "42"; 
     } 
    } 

    GetValue(): number { 
     return this.Value; 
    } 
} 

回答

1

不能使用ES2015laterclass让你调用构造函数没有new关键字。在链接文档的第9.2.1节的第2步中,调用没有new关键字的类构造函数应导致引发TypeError。 (如果你在TypeScript中定位ES5,你会得到一些在运行时可以工作的东西,但是如果你的目标是ES2015或者更高版本,你将会得到运行时错误,所以最好不要这样做。)所以要实现你的接口,你需要使用pre -ES2015构造函数代替。


顺便说一下,new(arg: number)签名需要返回类型。例如:

interface A { 
(): string; 
    new(arg: number): AInstance; // return something 
    GetValue(): number; 
} 
// define the instance type 
interface AInstance { 
    instanceMethod(): void; 
} 

下面是实现的一个方法。首先,做一个classAInstance

class _A implements AInstance { 
    constructor(arg: number) { } // implement 
    instanceMethod() { } // implement 
} 

然后,做一个可以带或不带new调用的函数:

const AFunctionLike = 
    function(arg?: number): AInstance | string { 
    if (typeof arg !== "undefined") { 
     return new _A(arg); 
    } 
    return "string"; 
    } as { new(arg: number): AInstance,(): string }; 

我已经决定,如果调用AFunctionLike与参数,那么你将获得AInstance,否则您将获得string。如果您的运行时支持它,您还可以通过new.target明确检查是否使用了new

另外请注意,我不得不断言AFunctionLike是newable(与最后一行as条款),因为目前尚未有其他的方式来告诉打字稿是一个独立的函数可以用new被调用。我们差不多完成了。

const A: A = Object.assign(
    AFunctionLike, 
    { 
    GetValue() { 
     return 1; 
    } 
    } 
); 

A已经通过使用实现GetValue()对象合并AFunctionLike形成:我们可以如下声明A类型的值。您可以使用Object.assignspread syntax进行合并。


就是这样。你可以验证这在运行时on the TypeScript Playground。祝你好运!