在 TypeScript 中混合到已经实例化的对象

Mixin in TypeScript to already instantiated Object

我正在使用一个外部库,returns 回调中 A 类型的实例化对象 a,其中 A 被定义为 接口A的class实现不被外部模块导出):

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

现在我想将 B 类型的混合对象添加到 A 的现有实例中:

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

我目前的做法有点糟糕:

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)
});

现在有人知道更好的方法吗:

这个怎么样:

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;

并在您的调用代码中:

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

Typescript Playground

一个问题:B 的新实例的原型将在 B.prototype,但 A 的实例将没有 B.prototype 的原型。

更新

原型差异的结果将导致以下结果:

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

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

因此您应该决定结果对象的类型:

  • A 的实例,增加了 B 的成员

    那么new B(a)就没有意义了;静态 B.augment<T>: T & B 方法会更合适

  • B 的实例,增加了 A 的成员;并且 instanceof 将有效工作