Dyna Dyna - 11 months ago 39
Javascript Question

Mixin in TypeScript to already instantiated Object

I'm using an external library, that returns an instantiated Object

of Type
in a callback, where
is defined as an Interface (the class imlementation of
is not exported by the external module):

extLib.on("someEvent", ((a: A) => { /*...*/ });

Now I'd like to add a mixin Object of Type
to the already existing instance of

class B {
someExtension() { /* ... */ }

My current approach is somewhat lousy:

function Add_B(a: A): (A & B) {
// cast to intersection type
let _a = a as (A & B);
_a.someExtension = () => { /* ... */ }
return _a;

extLib.on("someEvent", ((a: A) => {
let _a = Add_B(a);
// mixin achieved, _a is of type (A & B)

Now does someone know of a better approach that would:

  • Allow
    to have callable constructor and have
    be newable

  • Result in less/cleaner code

  • Has more expressive typings than the
    A & B
    intersection type

  • Would allow for
    properties on

  • Doesn't mess with the prototype chain too heavily (think

Answer Source

How about this:

interface A {
    prop: string;

class B {
    // so the same function can be shared between instance of B and instances of A & B
    static someExtensionStatic = () => { /* ... */ }

    someExtension = B.someExtensionStatic;
    readonly prop2: number;
    constructor(a?:A) {
        if (a) {
            let a1 = a as AandB;
            a1.someExtension = B.someExtensionStatic;
            return a1;

type AandB = A & B;

and in your calling code:

extLib.on("someEvent", ((a: A) => {
    let _a = new B(a) as AandB;
    // mixin achieved, _a is of type (A & B)

Typescript Playground

One issue: the prototype of new instances of B will be at B.prototype, but instances of A will not have the prototype of B.prototype.


A consequence of the difference in prototype will result in the following:

var b1 = new B();
var isInstanceOf = b1 instanceof B; // true

var b2 = new B(a);
isInstanceOf = b2 instanceof B;     // false

Therefore you should decide the type of the resulting object:

  • an instance of A, augmented with the members of B

    In that case new B(a) doesn't make sense; a static B.augment<T>: T & B method would be more fitting

  • an instance of B, augmented with members of A; and instanceof will work sensibly