首页 > 解决方案 > 在 TypeScript 中使用“替代模式”混合

问题描述

我不明白 TypeScript 关于混合模式的替代模式的文章。我看到当我像在网站上那样执行代码时,我得到了混合的方法,但我没有得到属性。例如这个例子

我将属性添加z = 1;Jumpable、创建我的类和 console.log z,但值为undefined。相反,如果我使用了Constrained Mixins模式,它会按预期工作,但我并不特别关心它的外观,并希望我在使用 Alternative Pattern 时做错了什么。有没有人有任何指导?

参考代码:

// Code copied from https://www.typescriptlang.org/docs/handbook/mixins.html#alternative-pattern

// Each mixin is a traditional ES class
class Jumpable {
  z = 1;
  jump() {
    console.log('Jumped');
  }
}

// Including the base
class Sprite {
  x = 0;
  y = 0;
}

// Then you create an interface which merges
// the expected mixins with the same name as your base
interface Sprite extends Jumpable {}
// Apply the mixins into the base class via
// the JS at runtime
applyMixins(Sprite, [Jumpable]);

let player = new Sprite();
console.log(player.z);

// This can live anywhere in your codebase:
function applyMixins(derivedCtor: any, constructors: any[]) {
  constructors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

标签: javascripttypescriptmixins

解决方案


这种模式没有考虑属性初始化,即它忽略了 mixin 的构造函数。这就是为什么 mixins 根本不应该有constructors,最好不要使用class语法。(注意这z = 1;不是类属性,它是.z在构造函数中创建实例属性的语法糖)。

要使用此模式,请提供特定于 mixin 的初始化方法:

class Jumpable {
  z: number;
  initJumpable() {
    this.z = 1;
  }
  jump() {
    console.log('Jumped');
  }
}

class Sprite {
  x = 0;
  y = 0;
  constructor() {
    this.initJumpable()
  }
}

interface Sprite extends Jumpable {}

applyMixins(Sprite, [Jumpable]);

推荐阅读