Home > OS >  How should I make an abstract method that can be either async or not?
How should I make an abstract method that can be either async or not?

Time:01-27

I'm implementing a base class, and want to provide a way for the derived classes to handle something. However, some derived classes will want to handle async'ly, and some will not. How can I accomplish that?

My current solution (playground link):

abstract class BaseHandler {
    protected handleException?(exception): void;
    protected handleExceptionAsync?(exception): Promise<void>;

    async handle() : Promise<void> {
        try {
               // ... stuff
        } catch (exception) {
            // ... exception stuff
            if (this.handleExceptionAsync){
                await this.handleExceptionAsync(exception);
            } else {
                this.handleException(exception);  // Cannot invoke an object which is possibly 'undefined'.(2722)          
            }            
        }
    }
}

CodePudding user response:

Since it is ok to call await on synchronous functions, you can simply make the return type a union:

abstract class BaseHandler {
    protected handleException(exception): void | Promise<void>;

    async handle() : Promise<void> {
        try {
            // ... stuff
        } catch (exception) {
            // ... exception stuff
            await this.handleException(exception);
        }
    }
}

CodePudding user response:

the question marks are the reason for the error, If you are going to keep them, then you just need to add ! after this.handleException ! (exception) By telling typescript compiler that, it is NOT undefined in that line.

following the explanation, you can do:

  1. adding ! sign
abstract class BaseHandler {
    protected handleException?(exception): void;
    protected handleExceptionAsync?(exception): Promise<void>;

    async handle() : Promise<void> {
        try {
               // ... stuff
        } catch (exception) {
            // ... exception stuff
            if (this.handleExceptionAsync){
                await this.handleExceptionAsync(exception);
            } else {
                this.handleException!(exception);  // Cannot invoke an object which is possibly 'undefined'.(2722)          
            }            
        }
    }
}
  1. or simply delete ? sign from the definition
abstract class BaseHandler {
    protected handleException(exception): void;
    protected handleExceptionAsync(exception): Promise<void>;

    async handle() : Promise<void> {
        try {
               // ... stuff
        } catch (exception) {
            // ... exception stuff
            if (this.handleExceptionAsync){
                await this.handleExceptionAsync(exception);
            } else {
                this.handleException(exception);  // Cannot invoke an object which is possibly 'undefined'.(2722)          
            }            
        }
    }
}
  •  Tags:  
  • Related