TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Mixins not working as expected for generic types

Open angelaki opened this issue 3 years ago • 2 comments

🔎 Search Terms

Combinations of mixin generic type lost unknown

🕗 Version & Regression Information

TS 4.8.2

⏯ Playground Link

https://www.typescriptlang.org/play?#code/MYGwhgzhAEDiCmA7eAnAlsAsgewCbxAB4AVAPmgG8AoaW6ANzBAFd4B+ALmmIG4qBfKlVCQYAYWwBbAA7ZkiAC4AhSPBLlqdaJLwFOcJKgw58RMn0HDwUaJgCeEmXKQLo8AB4KkucVNnzlVUIIBXREAHMNGjpcbAAKAEpKaK1aAHo092g0GDADZHQsXSIQsMiU1OA5EOgsgF5oBQALHIA6HVM+LUFLD1kUVwU7aXhoAEEAI1KwYAUJRFLmWewUEmgG7AmAK3hZ8gawKdCZ12QAd2g41uuwFHCILjBEOwBtAF0kuvJeIT6V1wAZsxELM0HJoBA0DIQPBMGh3GhECQADTcRz+FxuTzeGCTaazeaLZardHORQqCBqMikUhxCnwLjEUkBJKaOiHfGuEQ2ADKUOkMLhCMQWK8iB80HpyVSdEk8PguES0pllWqrnqjRaEHaxS6KsE3SEWhQ8AUzBQIr50Nh8MRFiE3JgQoVzMxHjFEsh1qFiLirvJQVKiMirIqsSVbJlGSyOWgeQQBWMxUIwIA1ohsGdEOQAGT5IxFUzBULB8hNVDwACEFS0VQW6vWmraHQIetoPV+7n6gOBoPB4UMhR9SLIEYqJrNFugQJBCjBIq9AptwpI-tc7px4yOKBOhNCSwUK0Ia-p6hpdNUjLXoZVce3J2gjugVqXw9Fm6lkdv2nlipv35lOsag1Zpm11Gt9Qg9sjRVCdzUtflBVtRA22gDsrFEWxfwAVWkNd33FGAB0TLBkOLMpaQSP0-DJQJKXI0t-1ocMmNSDIVGAVNshFZpRiDCIAFoJmYSFkBscsTVaSVmFcM4mjsCFsEfPwQAwMAvFwNgoOU+takbUDtRbEBUJ6IA

💻 Code

class GenericModel<T> {
    value?: T;
}

class ComponentBase<T> {
    model?: GenericModel<T>;
}

class MyComponent extends ComponentBase<string> {
    do() {
        //Using my ComponentBase model.value is of type 'string' - as expected
        const x = this.model;
    }
}

export type AbstractConstructor<T = object> = abstract new (...args: any[]) => T;

export function simpleMixin<T, TComponent extends AbstractConstructor<ComponentBase<T>>>(Base: TComponent) {
    abstract class SimpleMixin extends Base {
        mixed() {
            const x = this.model;
        }
    }

    return SimpleMixin;
}

class MixedComponent extends simpleMixin(ComponentBase<string>) {
    do() {
        //Using this 'simpleMixin' ComponentBase model.value is of type 'string & unknown'! Why is unknown getting mixed in here? TypeScript could / should know, that it is of type string only!
        const x = this.model;
    }
}

export function genericMixin<T>() {
    return function simpleMixin<TComponent extends AbstractConstructor<ComponentBase<T>>>(Base: TComponent) {
        abstract class SimpleMixin extends Base {
            mixed() {
                const x = this.model;
            }
        }

        return SimpleMixin;
    }
}

class MixedUpComponent extends genericMixin<string>()(ComponentBase<string>) {
    do() {
        //Using this 'genericMixin' ComponentBase model.value is of type 'string' again. But the mixin looks pretty complicated (and needs to be applied pretty unintuitive). But it seams to be the only solution right now, since 'simpleMixin' isn't working for some reason.
        const x = this.model;
    }
}

🙁 Actual behavior

As you can see in the commented lines, the type information is somehow lost / mixed up with unknown.

🙂 Expected behavior

Keep my generic type information

angelaki avatar Sep 20 '22 17:09 angelaki

Please give concrete expected / actual behaviors. I can't know what you expect to happen, or why, based on these descriptions.

RyanCavanaugh avatar Sep 21 '22 23:09 RyanCavanaugh

@RyanCavanaugh have you checked the playground link? I reduced the code to the four lines showing my problem. Now I put in the whole code and added some more comments.

Keeping the generic Type with the mixin is pretty complicated right now.

angelaki avatar Sep 22 '22 08:09 angelaki

This issue has been marked as 'Unactionable' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

github-actions[bot] avatar Jun 08 '23 03:06 github-actions[bot]