3

I have a number of models that will be acted upon by their related controller. However there is a bit of boilerplate I would like to factor out of each controller and I thought I might be able to use a "base controller" with generics.

Hopefully example below shows what I am trying to accomplish - instantiate each controller with a factory method which will result in an instance of the controller being returned containing its specific model instantiated with its defaults.

The challenge specifically is that I can't seem to get past the

'X' only refers to a type, but is being used as a value here

error in the factory. The abstract class model seems to be the right approach, but open to all suggestions. Playground

abstract class ModelA {
    propA: string;
    propB?: number;
    propC?: number;
    constructor() {
        this.propA = "here"
    }
}

interface ModelB {
    propA: string,
    propB: number,
    propC: number,
}

class BaseController<X> {

    private _model: X

    constructor(payload: X) {
        this._model = payload
    }

    public factory():BaseController<X>
    {
        let model:X;
        model = new X();
        return new BaseController<X>(model);
    }
}

class ModelAController extends BaseController<ModelA> {
    constructor(payload: ModelA) {
        super(payload);
    }
}

let x = ModelAController.factory();

1 Answer 1

1

You want to call factory as a static method, whereas this is not static.

In order to make it work, you need:

  1. to make factory static.
class BaseController<X> {

    private _model: X

    constructor(payload: X) {
        this._model = payload
    }

    static factory() // <------- SHOULD BE STATIC
    {
        let model:X;
        model = new X();
        return new BaseController<X>(model);
    }
}

  1. Change this logic:
        let model:X;
        model = new X();

X is a generic, it is not a runtime value. It is not allowed to use it as a runtime value;

Consider this example:

abstract class ModelA {
    propA: string;
    propB?: number;
    propC?: number;
    constructor() {
        this.propA = "here"
    }
}

interface ModelB {
    propA: string,
    propB: number,
    propC: number,
}

class BaseController<X> {

    private _model: X

    constructor(payload: X) {
        this._model = payload
    }

    static factory<Model extends new () => any>(Model: Model) {
        return new BaseController(new Model());
    }
}

class ModelAController extends BaseController<ModelA> {
    constructor(payload: ModelA) {
        super(payload);
    }
}

class AnyClass {
    hello = 'Hello'
}

let x = ModelAController.factory(AnyClass);

I'm not sure if this example works for you, but at least this compiles.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.