TypeScript mixin'leri (Angular'da) nasıl çalışır?


Şu anda Angular'da bileşenimin işlevlerini genişletmek için mixin'ler kullanıyorum. Tüm mixin'lerim şöyle görünüyor:

export function mixinTest<T extends AbstractConstructor<ComponentBase>>(Base: T) {
    abstract class MixinTest extends Base {
        //Logic here
    };

    return MixinTest;
}

export function mixinTest2<T extends AbstractConstructor<ModelComponentBase<unknown>>>(Base: T) {
    abstract class MixinTest2 extends Base {
        //Logic here
    };

    return MixinTest2;
}

ComponentBase, birkaç tane sahip olduğum bir temel bileşendir. Miras alma ve mixin karışımı kullanıyorum. Miras alma, mantıklı olduğunda (Angular'ın notasyonlarını (@Input, @Output vb.) kaybetmemek için) ve özel mantık için mixin fonksiyonları kullanıyorum.

Şimdi benim de bir ModelComponentBase<T>’im var, ve bunun bir model: T özelliği bulunuyor. Eğer şimdi ComponentBase’den türeyen bir mixin eklersem, model özelliğini kaybediyorum: derleyici bana Property 'model' does not exist on type 'TestComponent'. diyor:

export class TestComponent extends mixinTest(mixinTest2(ModelComponentBase))<Task> {
    method(): void {
        this.model$.subscribe(t => this.task = <Task>t);
    }
    task: Task;
}

Ama işe yarıyor, eğer sıraya dikkat edersem:

export class TestComponent extends mixinTest2(mixinTest(ModelComponentBase))<Task> {
    method(): void {
        this.model$.subscribe(t => this.task = <Task>t);
    }
    task: Task;
}

veya sadece bir mixin kullanın:

export class TestComponent extends mixinTest(ModelComponentBase)<Task> {
    method(): void {
        this.model$.subscribe(t => this.task = <Task>t);
    }
    task: Task;
}

ve bu çalışıyor bile, eğer fonksiyonları birden fazla adımda karıştırırsam:

const ctor = mixinTest2(ModelComponentBase);
const ctor2 = mixinTest(ctor);
export class TestComponent extends ctor2<Task> {
    method(): void {
        this.model$.subscribe(t => this.task = <Task>t);
    }
    task: Task;
}

Bu neden fark yaratıyor? Önemi olmadığını düşünmüştüm? Bu arada: AbstractContructor Angular Material'dan alınmıştır: export declare type AbstractConstructor<T=object>=abstract new (...args: any[]) => T;

Yani sorularım şunlar:

  1. Mixins'i doğru kullanıyor muyum? Yoksa mixinTest'im zaten hatalı mı?
  2. Sıra neden önemlidir? Karışımdaki miktar neden fark yaratır?
  3. ModelComponentBase<unknown> ile mixin kullanmak modelin unknown | T türüne dönüşmesine neden olur. mixinTest2 ile genel parametreleri kullanmanın bir yolu var mı?