Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript error : A 'super' call must be the first statement in the constructor when a class contains initialized properties

I have the following typescript errors in my project.. let me share a sample so you can see what am dealing with.

module CoreWeb {
export class Controller implements IController {
    public $q;
    public $rootScope;
    public $scope:ng.IScope;
    public $state:ng.ui.IStateService;
    public $translate:ng.translate.ITranslateService;
    public appEvents;
    public commonValidationsService;
    public defaultPagingOptions = {
        currentPage: 1,
        pageSize: 10,
        totalServerItems: 0,
        maxSize: 5
    };
    public detailModelName:string;
    public filter:string;
    public listModelName:string;
    public mode;
    public modelDataService;
    public modelDefaultProperty:string;
    public ngDialog;
    public notificationsService;
    public pagingOptions:IPagingOptions;
    public selectionStatus:boolean;
    public serviceCreateFunction:string;
    public serviceGetAllCanceller:ng.IDeferred<any>;
    public serviceGetAllFunction:string;
    public serviceGetOneFunction:string;
    public serviceUpdateFunction:string;
    public showInactive:boolean;
    public tableAction:number;
    public tableActions:ITableAction[];
    public titleDataFactory;
    public validationOptions;
    public validationRules;
    public orderBy = null;
    public orderType = null;
    constructor(
        $q:ng.IQService,
        $rootScope,
        $scope:ng.IScope,
        $state,
        $translate:ng.translate.ITranslateService,
        appEvents,
        commonValidationsService,
        detailModelName:string,
        listModelName:string,
        modelDataService,
        modelDefaultProperty:string,
        ngDialog,
        notificationsService,
        serviceCreateFunction:string,
        serviceGetAllFunction:string,
        serviceGetOneFunction:string,
        serviceUpdateFunction:string,
        titleDataFactory
    ) {
        this.$q = $q;
        this.$rootScope = $rootScope;
        this.$scope = $scope;
        this.$state = $state;
        this.$translate = $translate;
        this.appEvents = appEvents;
        this.commonValidationsService = commonValidationsService;
        this.detailModelName = detailModelName;
        this.listModelName = listModelName;
        this.modelDataService = modelDataService;
        this.modelDefaultProperty = modelDefaultProperty;
        this.ngDialog = ngDialog;
        this.notificationsService = notificationsService;
        this.serviceCreateFunction = serviceCreateFunction;
        this.serviceGetAllCanceller = $q.defer();
        this.serviceGetAllFunction = serviceGetAllFunction;
        this.serviceGetOneFunction = serviceGetOneFunction;
        this.serviceUpdateFunction = serviceUpdateFunction;
        this.titleDataFactory = titleDataFactory;

        this.mode = $rootScope.modeEnum.none;
        this.pagingOptions = this.defaultPagingOptions;
        this.selectionStatus = false;
        this.showInactive = false;
        this.tableAction = null;
        this.tableActions = [
            {id: 1, name: "Activate"},
            {id: 2, name: "Deactivate"}
        ];
        this.validationOptions = {showErrors: commonValidationsService.modes.property, showNotification: true};

        this.activate();
    }

This is the class that extends the controller class.. one among many others

declare var App: ng.IModule;

module CoreWeb {
    export class EntityMasterController extends Controller {
        private currenciesDataSet;
        private entity: IEntityMasterModel;
        private merchandisingConstants;
        private typeAheadOptions;

    constructor(
        $q:ng.IQService,
        $rootScope,
        $scope:ng.IScope,
        $state,
        $translate:ng.translate.ITranslateService,
        appEvents,
        commonValidationsService,
        entityDataService,
        merchandisingConstants,
        ngDialog,
        notificationsService,
        titleDataFactory
    ) {
        this.merchandisingConstants = merchandisingConstants;
        super(
            $q,
            $rootScope,
            $scope,
            $state,
            $translate,
            appEvents,
            commonValidationsService,
            "entity",
            null,
            entityDataService,
            "name",
            ngDialog,
            notificationsService,
            "createEntity",
            "getCurrentEntity",
            "getEntity",
            "updateEntity",
            titleDataFactory
        );
    }

Now, if I initialize the merchandisingConstants before the super call like done above. I get the following error during gulp and my page does not display anything. A super call must be the first statement in the constructor when a class contains initialized properties or has parameter properties. I have tried all ways I can think of to fix these errors any idea of how I can go about this?

like image 330
KinyoriDeStephen Avatar asked Jul 29 '15 13:07

KinyoriDeStephen


2 Answers

When you extend a class, your constructor:

  1. Must call super()
  2. Must do that before it does anything else

In your instance, you just need to re-order things:

declare var App: ng.IModule;

module CoreWeb {
    export class EntityMasterController extends Controller {
        private currenciesDataSet;
        private entity: IEntityMasterModel;
        private merchandisingConstants;
        private typeAheadOptions;

    constructor(
        $q:ng.IQService,
        $rootScope,
        $scope:ng.IScope,
        $state,
        $translate:ng.translate.ITranslateService,
        appEvents,
        commonValidationsService,
        entityDataService,
        merchandisingConstants,
        ngDialog,
        notificationsService,
        titleDataFactory
    ) {
        // Must be first
        super(
            $q,
            $rootScope,
            $scope,
            $state,
            $translate,
            appEvents,
            commonValidationsService,
            "entity",
            null,
            entityDataService,
            "name",
            ngDialog,
            notificationsService,
            "createEntity",
            "getCurrentEntity",
            "getEntity",
            "updateEntity",
            titleDataFactory
        );

        this.merchandisingConstants = merchandisingConstants;
    }
like image 138
Fenton Avatar answered Oct 06 '22 06:10

Fenton


This is quite a hack, but it is a simple workaround to the problem:

    super(
        (this.merchandisingConstants = merchandisingConstants, $q),
        $rootScope,
        $scope,
        $state,
        $translate,
        appEvents,
        commonValidationsService,
        "entity",
        null,
        entityDataService,
        "name",
        ngDialog,
        notificationsService,
        "createEntity",
        "getCurrentEntity",
        "getEntity",
        "updateEntity",
        titleDataFactory
    );

That uses the somewhat weird and not-often-useful JavaScript , operator to stuff the assignment in there as a side effect. You could do it with any of the parameters, really, but I did it with the first one. The comma operator — which is not the same as the comma that separates arguments to a function, even though of course it's exactly the same character — lets you string together a list of expressions, all of which will be evaluated. Only the last one is used as the value of the overall expression.

Thus, by doing that, you do your assignment while the argument list is being evaluated. The value of the first parameter will still be $q, but the assignment will happen too, before the function call to super() is made.

like image 30
Pointy Avatar answered Oct 06 '22 04:10

Pointy