Is it possible to access a property of a base class using Generics in Typescript?

1

I have the following class that will be the basis for the entities of the application

namespace Base {
    export abstract class BaseEntity {
        endpoint: string;
        public abstract getId(): string;
    }
}

and the implementation of this class is given in this way:

namespace Example {
    export class Account extends Base.BaseEntity {
        accountId?: string;
        name?: string;
        constructor() {
            super();
            this.endpoint = "accounts";
        }

        public getId(): string {
            return this.accountId;
        }
    }
}

the purpose of this is to be able to obtain the value of the property endpoint of each class to know the url of the web method defined in a Web Api.

Here the example:

namespace Base {
    export class BaseService<T extends BaseEntity> {
        private url: string;
        constructor(
            private $q: angular.IQService,
            private $http: angular.IHttpService) {
            this.url = 'http://localhost:81/api/${(<BaseEntity>T).endpoint}'; //ERROR: 'T' only refers to a type, but is being used as a value here.
        }
    }
}

but I get the following error about this ${(<BaseEntity>T).endpoint} statement:

  

// ERROR: 'T' only refers to a type, but is being used as a value here.

    
asked by pBlackmouth 08.03.2017 в 02:22
source

1 answer

0

The problem is that endpoint is a member of the class BaseEntity and on the other hand T is a type, you can not apply type assertion <BaseEntity> to a type but to a variable.

The only solution for compile is to store an instance of type T at the moment that an instance of BaseService is built, which can be called to its property endpoint

namespace Base {
    export class BaseService<T extends BaseEntity> {
        private url: string;
        constructor(
            private $q: angular.IQService,
            private $http: angular.IHttpService,
            private entity: T) {
            this.url = 'http://localhost:81/api/${entity.endpoint}';
        }
    }
}

However, a better solution would be to remove the endpoint property of the BaseEntity class since it does not really belong to the entity but instead place it in BaseService so that each service that inherits it can set its own endpoint.

namespace Base {
    export abstract class BaseEntity {
        public abstract getId(): string;
    }
}

namespace Example {
    export class Account extends Base.BaseEntity {
        accountId?: string;
        name?: string;
        constructor() {
            super();
        }

        public getId(): string {
            return this.accountId;
        }
    }
}

namespace Base {
    export class BaseService<T extends BaseEntity> {
        private url: string;
        constructor(
            private $q: angular.IQService,
            private $http: angular.IHttpService,
            private endpoint: string) {
            this.url = 'http://localhost:81/api/${this.endpoint}';
        }
    }
}

namespace Example {
    export class AccountService extends Base.BaseService<Account>
    {
        constructor(
            $q: angular.IQService,
            $http: angular.IHttpService,
            endpoint: string) {
            super($q, $http, 'accounts');
        }
    }
}
    
answered by 25.07.2017 / 07:04
source