首页 > 解决方案 > 具有默认属性值的 Typescript mixins(从新的 MyClass 派生)

问题描述

我正在使用 Typescript 中的一些 mixin 进行试验,并且已经掌握了使用几种不同方法构建 mixin 的基础知识。在所有这些中,我都遇到了同样的错误。

这是我的混合类:

export class OnDestroyMixin implements OnDestroy {

    public destroyStream: Subject<void> = new Subject();

    ngOnDestroy(): void {
        console.log(`on destroy from mixin`);

        this.destroyStream.next();
        this.destroyStream.complete();
    }
}

并且每当调用 on destroy 函数(在将其混合到另一个类之后)时,this.destroyStream它都不存在,所以我得到一个Cannot read property 'next' of undefined错误。

我考虑过在构造函数中设置它,但我不确定构造函数在 mixins 中是如何工作的......

我认为这应该是可能的。

我目前使用的 mixin 方法是一个 mixin 装饰器:

export function Mixin(baseCtors: Function[]) {
    return function (derivedCtor: Function) {
        baseCtors.forEach(baseCtor => {
            Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
                const descriptor = Object.getOwnPropertyDescriptor(baseCtor.prototype, name);

                if (name === 'constructor')
                    return;

                if (descriptor && (!descriptor.writable || !descriptor.configurable || !descriptor.enumerable || descriptor.get || descriptor.set)) {
                    Object.defineProperty(derivedCtor.prototype, name, descriptor);
                } else {
                    derivedCtor.prototype[name] = baseCtor.prototype[name];
                }

            });
        });
    };
}

我从网上某处复制了它,但正如我所说,我尝试了几种不同的方法,它们基本上都将属性从一个原型复制到另一个原型。

标签: typescriptmixins

解决方案


这个问题的根本原因是当你在一个类上定义一个属性值时,当它被转换为 JavaScript 时,这个值是在构造函数中设置的。上面的 mixin 代码专门忽略了构造函数。这里真正的解决方案是将 2 个类构造函数合并在一起。

Typescript 中似乎有两种不同的 mixins 方法。类似于我的问题中的一种方法,我们遍历原型属性并将它们从一个类复制到另一个类,而在另一个类中,我们只需返回一个扩展原始类的新类

function Flies<TBase extends Constructor>(Base: TBase) {
    return class extends Base {
        fly() {
            alert('Is it a bird? Is it a plane?');
        }
    };
}

我原以为我无法在 Angular 中使用它,因为它是一个返回新类的函数,但它完全有可能如此处所示

class SourceClass{}

@Component({
    selector: 'some-selector',
    templateUrl: './some-selector.html',
    styleUrls: ['./some-selector.scss']
})
export class SampleMixedClass extends Flies(SourceClass) {}

推荐阅读