TypeScript中的Mixins

aar*_*acy 6 mixins typescript

我正在玩TypeScript,我有一些功能混合,Eventable而且Settable我想混合到一个Model类(假装它像Backbone.js模型):

function asSettable() {
  this.get = function(key: string) {
    return this[key];
  };
  this.set = function(key: string, value) {
    this[key] = value;
    return this;
  };
}

function asEventable() {
  this.on = function(name: string, callback) {
    this._events = this._events || {};
    this._events[name] = callback;
  };
  this.trigger = function(name: string) {
    this._events[name].call(this);
  }
}

class Model {
  constructor (properties = {}) {
  };
}

asSettable.call(Model.prototype);
asEventable.call(Model.prototype);
Run Code Online (Sandbox Code Playgroud)

上面的代码工作正常,但如果我尝试使用其中一个混合方法,则无法编译(new Model()).set('foo', 'bar').

我可以解决这个问题

  1. 添加interfacemixins的声明
  2. 声明哑get/ set/ on/ trigger在方法Model声明

虚拟声明周围有一个干净的方法吗?

Ste*_*man 12

这是使用interfacesstatic create()方法处理mixins的一种方法.接口支持多重继承,因此可以防止你必须重新定义interfaces你的mixins,并且该static create()方法负责给你一个实例Model()作为一个IModel(<any>需要强制转换编译器警告.)你需要复制所有的为您的成员定义ModelIModel它吮吸,但它似乎是最干净的方式来实现你的打字稿的当前版本想要什么.

编辑:我已经确定了一种稍微简单的方法来支持mixins,甚至创建了一个帮助类来定义它们.细节可以在这里找到.

function asSettable() {
  this.get = function(key: string) {
    return this[key];
  };
  this.set = function(key: string, value) {
    this[key] = value;
    return this;
  };
}

function asEventable() {
  this.on = function(name: string, callback) {
    this._events = this._events || {};
    this._events[name] = callback;
  };
  this.trigger = function(name: string) {
    this._events[name].call(this);
  }
}

class Model {
  constructor (properties = {}) {
  };

  static create(): IModel {
      return <any>new Model();
  }
}

asSettable.call(Model.prototype);
asEventable.call(Model.prototype);

interface ISettable {
    get(key: string);
    set(key: string, value);
}

interface IEvents {
    on(name: string, callback);
    trigger(name: string);
}

interface IModel extends ISettable, IEvents {
}


var x = Model.create();
x.set('foo', 'bar');
Run Code Online (Sandbox Code Playgroud)

  • 即将发布此内容.确实应该扩展TypeScript以支持类的混合,因为很多JS库目前都使用它(例如Backbone.js). (6认同)
  • +1需要部分类和/或mixins (2认同)

Eri*_*ton 2

几年前,Typescript 中内置了一种新方法,称为“mixin 类”。文档中没有很好地介绍它,但他们确实有一个注释良好的示例来很好地描述该模式。适用于您的情况,它可能看起来像:

type Constructor = new (...args: any[]) => {}

function Settable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    _props: Record<string, any> = {};

    get(key: string) {
      return this._props[key];
    }

    set(key: string, value: any) {
      this._props[key] = value;
      return this;
    }
  }
}

function Eventable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    _events: Record<string, () => void> = {};

    on(name: string, callback: () => void) {
      this._events[name] = callback;
    }

    trigger(name: string) {
      this._events[name].call(this);
    }
  }
}

class Model extends Settable(Eventable(Object)) {
  constructor(properties = {}) {
    super();
  }
}
Run Code Online (Sandbox Code Playgroud)

这将为您提供所需的打字功能,以便您能够在通话时(new Model()).set('boo', 'bar')获得完整的打字支持。没有虚拟声明。