如何将 Javascript "partial classes" 与 TypeScript 样式 class 定义一起使用

How can I use Javascript "partial classes" with TypeScript style class definition

我的应用程序有一个 api 包装器 class 最初是通过在 TypeScript 中输入它创建的,copying/pasting javascript 到我的应用程序中。

所以 class def 看起来像这样:

var SiteApi = (function () {
  function SiteApi(initially) 
  {
    //stuff
  }

  SiteApi.prototype.method1 = function(){/*stuff*/};
  SiteApi.prototype.method2 = function(){/*stuff*/};

  return SiteApi;
})();

现在,当它们位于管理页面时,我想添加一个额外的 admin.js 文件,其中将包含管理方法。例如

SiteApi.prototype.Admin.method1 = function(){/*stuff*/};

我找到了一个可以实现我想要的 "end result" 的示例:

// file main
function SomeObject() {
    for (var i = 0, ii = SomeObject.Partial.length; i < ii; i++) {
         SomeObject.Partial[i].apply(this, arguments);
    }
}

SomeObject.Partial.SomeName = function() {
   ...
}

// file extra
SomeObject.Partial.SomeOtherName = function() {
   ...
}

(来自:Is it possible to give javascript partial class behavior like C# or monkey patching like Ruby does?

但是,他们使用的 class 定义类型不同。

如何在保持 TypeScript 风格 class 定义的同时做一些类似于此示例的操作来添加管理功能?

作为参考,我们这样使用 class:

siteApi = new SiteApi();

所以我想还需要一行代码将管理功能绑定到其中。

注意,我可以使用 SiteApi.admin_method1 之类的东西,但问题是使用 TypeScript 样式 classes 原型是在定义中定义的,对象是执行的,所以它不会以后如何添加更多原型似乎很简单。

选项 1

扩展 SiteApi 但隐藏原始内容,例如您之后加载的 admin.js 会包含类似

的内容
SiteApi = (function (old_SiteApi) {
    function SiteApi() {
        old_SiteApi.apply(this, arguments);
        // further construction
        this.admin_method1 = function () {/* some admin instance method */};
    }
    SiteApi.prototype = Object.create(old_SiteApi.prototype);
    // add more prototype things
    SiteApi.prototype.admin_method2 = function () {/* admin stuff through prototype */},
    return SiteApi;
}(SiteApi));

选项 2

SiteApi 知道稍后会有更多内容,例如原来的定义会变成

var SiteApi = (function () {
    function SiteApi(initially) {
        //stuff
        var i;
        for (i = 0; i < SiteApi.Extras.length; ++i) {
            SiteApi.Extras[i].apply(this);
        }
    }
    SiteApi.Extras = [];

    SiteApi.prototype.method1 = function () {/* stuff */};
    SiteApi.prototype.method2 = function () {/* stuff */};

    return SiteApi;
}());

那么admin.js就可以了

SiteApi.Extras.push(
    function () {
        // stuff to make `this` into an Admin object
        this.admin_method1 = function () {/* some admin instance method */};
    }
);

选项 3

SiteApi原型仍然暴露,如果你不需要做更多的构造,只需要新的方法,你可以简单地在admin.js

Object.assign(SiteApi.prototype, {
    admin_method1: function () {/* admin stuff through prototype */},
    admin_method2: function () {/* more admin stuff through prototype */}
});

最后一个选项是唯一会影响在 admin.js 加载之前创建的 SiteApi 实例的选项。

当然,您也可以将选项 2 和 3 混合在一起。同样,您可以使用选项 1,但将新构造函数称为不同的名称,而不是隐藏原始构造函数,例如 AdminApi,并使用它代替 SiteApi ] 在管理页面上。