B
B
BonBon Slick2022-01-16 23:31:48
typescript
BonBon Slick, 2022-01-16 23:31:48

How to use mixins on abstract classes?

// https://www.typescriptlang.org/docs/handbook/mixins.html

type Constructor<T = {}> = new (...args: any[]) => T;
type AbstractConstructor<T> = Function & { prototype: T };
// type ConstructorFunction = abstract new (...args: any[]) => any;
declare type ConstructorFunction<T extends Utilities> = new (...args: any[]) => T;
type Constructor2<T> = new (...args: any[]) => T

export default function Activatable<TBase extends Constructor2>(Base: TBase) {
    return class extends Base {
        // Mixins may not declare private/protected properties
        // however, you can use ES2020 private fields
        _scale = 111111111111111111111111;
        _isActivated = false;
        _timestamp = Date.now();

        activate() {
            this._isActivated = true;
        }

        deactivate() {
            this._isActivated = false;
        }

        setScale(scale: number) {
            this._scale = scale;
        }

        get scale(): number {
            return this._scale;
        }
    };
}

import Activatable from '@/store/module/abstract/mixin/countdown.ts'

abstract class AbstractModuleForm {...}
abstract class AbstractModuleCountdownForm extends Activatable(AbstractModuleForm)  {...}

class Test extends AbstractModuleCountdownForm {...}

All examples of the mixin constructor above break the code, throw hundreds of errors on all methods used, class parameters, including the one that is being extended.
As a result, the classes have mixin methods, but everything else flies.

The problem is that 2+ abstract classes from different modules have the same set of fields and methods, for example createdAt, updatedAt.
I'm trying to make a mixin, according to the documentation and answers to the CO, everything flies.
Error examples
  1. Generic type 'Constructor2' requires 1 type argument(s).
  2. Type 'TBase' is not a constructor function type.
  3. Cannot create an instance of an abstract class.
  4. Argument of type 'typeof A' is not assignable to parameter of type 'Constructor<{}>'.
  5. Cannot assign an abstract constructor type to a non-abstract constructor type.
  6. Cannot create an instance of an abstract class.
  7. A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
  8. Cannot create an instance of an abstract class.

  9. // these are all other classes that inherit the class with the mixin, all of the properties and methods are cut out
    TS2339: Property 'setFieldValueByFieldName' does not exist on type 'SecuredModuleFormUpdateAccount'.



Is there a working way for abstract mixin classes/methods in TS?
If so, is there a working example?

TS Playground

It is important to note that the library for vuex class moduels is used

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Belyaev, 2022-01-17
@BonBonSlick

Generic type 'Constructor2' requires 1 type argument(s).

Your Constructor2 type requires a generic argument, but here you use it without a generic: You can try this:function Activatable<TBase extends Constructor2>
Type 'TBase' is not a constructor function type.
this error came out of the previous one
Cannot create an instance of an abstract class.

Cannot assign an abstract constructor type to a non-abstract constructor type
everything swears correctly, abstract classes are abstract because they have abstract methods whose implementation must be in the heir, their construction will lead to errors and TS protects against this.
A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
The mixin accepts an arbitrary abstract class as input, without knowing about all its abstract methods, so it must also be abstract.
type AbstractConstructor<T> = Function & { prototype: T };
This one is incorrect...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question