Search code examples
typescripttyping

Implementation of abstract class as type


I want to define a type for a property of my class:

abstract class CoolStuff {
    protected abstract service: any;
}

This service is an abstract too:

abstract class BaseService<T,K> {
     // Code
}

So i'd expect this:

abstract class CoolStuff {
    protected abstract service: BaseService
}

But then the compiler expects me to define T and K. But these are already defined in the implemented Service:

class ActualService extends BaseService<Collection, Model>{
    // Code
}

So what i want to do is something along the lines of:

abstract class CoolStuff {
    protected abstract service: instanceof BaseService;
}

But how?


Solution

  • The best way to do this would be to make CoolStuff generic as well, and then you can specify the actual types in the derived classes of CoolStuff

    abstract class CoolStuff<T, K> {
        protected abstract service: BaseService<T, K>;
    }
    
    class CoolStuffWithActualService extends CoolStuff<Collection, Model> {
        protected service: ActualService
    }
    

    You might also get away with specifying any as a type parameter in CoolStuff, but this results in weaker typing in the base class as it can pass anything to BaseService which may be an issue.

    abstract class CoolStuff {
        protected abstract service: BaseService<any, any>;
    }
    
    class CoolStuffWithActualService extends CoolStuff {
        protected service: ActualService
    }
    

    Edit

    A third option would be to have the service type itself as a type parameter to CoolStuff and constrain it to be of type BaseService<any, any>

    abstract class CoolStuff<TService extends BaseService<any, any>> {
        protected abstract service: TService
    }
    
    class CoolStuffWithActualService extends CoolStuff<ActualService> {
        protected service!: ActualService
    }