【问题标题】:Mixin in TypeScript to already instantiated Object在 TypeScript 中混合到已经实例化的对象
【发布时间】:2017-02-05 10:49:59
【问题描述】:

我正在使用一个外部库,它在回调中返回类型为A 的实例化对象a,其中A 被定义为接口(@ 的类实现987654324@没有被外部模块导出):

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

现在我想将B 类型的mixin 对象添加到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)
});

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

  • 允许B 拥有可调用的构造函数,并让B 成为可更新的
  • 产生更少/更简洁的代码
  • A & B 交集类型更具表现力
  • 是否允许 readonly 属性在 B 上?
  • 不会过多地混淆原型链(想想static 成员) ?

【问题讨论】:

    标签: javascript object typescript interface mixins


    【解决方案1】:

    这个怎么样:

    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 将有效地工作

    【讨论】:

    • 不错。我想不出来的原因是我从来没有想过构造函数的返回值定义了 new B() 将是什么实例。我太习惯于 C# 构造函数不能有返回类型: )
    • @Dyna Typescript 既不能识别构造函数返回不同的类型,也不允许您指定构造函数的返回类型,这就是我们必须在调用代码中进行强制转换的原因: let _a = new B(a) as AandB;.
    • @Dyna 再想一想,我不知道使用构造函数返回任意类型有多大意义(可能是为什么 Typescript 不允许在构造函数上进行类型注释) .调用new B(a) 并返回不是具有原型B 的对象,而是与B 无关的对象(尽管与B 具有相同的成员)真的有意义吗?我可能会在B 上使用static 方法,并将其称为B.create()(返回B 的新实例)或B.create(a)(返回增强的A。这也将允许单独基于重载的类型。
    • @Dyna 更新答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多