【问题标题】:TypeScript: functional interface with constructorTypeScript:带有构造函数的函数式接口
【发布时间】:2017-10-18 12:17:00
【问题描述】:

我想要一个行为类似于 js 日期函数的类:

  1. 当通过new 调用时,它会创建一个类的实例。
  2. 当作为函数调用时,它会执行一些静态操作。

如何实现这个接口?

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

当前无法编译但在 Playground 中生成正确 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;
    }
} 

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您不能使用ES2015later class 让您调用没有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;
    }
    

    这是实现它的一种方法。首先,为AInstance创建一个class

    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 是可更新的(在最后一行使用 as 子句),因为目前没有其他方法可以告诉 TypeScript 可以使用 new 调用独立函数。

    现在我们差不多完成了。我们可以声明一个A 类型的值,如下所示:

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

    A 是通过将AFunctionLike 与实现GetValue() 的对象合并形成的。您可以使用Object.assignspread syntax 进行此合并。


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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      相关资源
      最近更新 更多