I don't understand TypeScript's article on Alternative Pattern for mixins. I see that when I execute the code as they have on the website, I get the methods mixed in, but I don't get properties. e.g. this example
I added the property z = 1; to Jumpable, create my class, and console.log z, but the value is undefined. If instead I used the Constrained Mixins pattern, it works as expected, but I don't particularly care for how that looks and was hoping that I'm doing something wrong with the Alternative Pattern. Does anyone have any guidance?
Code for reference:
// 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)
);
});
});
}
applyMixinsclearly shows that at no point a (necessary super)Jumpablecall is involved. Everything is just about copying properties from one prototype to another. Thus one achieves gluing together prototypal behavior but not the composition of properties which materialize just at instantiation/call time. For the OP's particular use case one was better off with aJumperclass andclass Sprite extends Jumper { /* ... */}.