NSwag: TypeScript: Set prototype of SwaggerException

Because the exception that’s thrown by the auto generated code doesn’t specify its prototype, one can’t be certain that a SwaggerException is the error being cought.

Example:

try {
    await (new MyClient()).myMethod()
} catch (err) {
    // Is the err a SwaggerException or something different?
    // We don't know because if the err is a SwaggerException, it's prototype is still Error
}

If SwaggerException got changed into this instead:

export class SwaggerException extends Error {
    message: string;
    status: number; 
    response: string; 
    result: any; 

    constructor(message: string, status: number, response: string, result: any) {
        super();

        this.message = message;
        this.status = status;
        this.response = response;
        this.result = result;

        Object.setPrototypeOf(this, SwaggerException.prototype);
    }
}

It would be possible to write this while also getting intellisense for SwaggerException:

try {
    await (new MyClient()).myMethod()
} catch (err) {
    if(err instanceof SwaggerException)
        console.log("SwaggerException!")
    else
        console.log("something else")
}

Object.setPrototypeOf is supported back to IE11

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 17 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Ok I think we’ll go with this:

  • Remove extends Error for instanceof compatibility (for free)
  • Add instance property isSwaggerException (for checks when the static method is not available)
  • Add static method isSwaggerException which checks if the object has isSwaggerException == true
    class SwaggerException {
        protected isSwaggerException = true; // hidden because it is only used with any

        public static isSwaggerException(obj: any): obj is SwaggerException {
            return obj.isSwaggerException === true;
        }
    }


    var x = {};
    if (SwaggerException.isSwaggerException(x)) {
         ....
    }

    // or

   if (x.isSwaggerException) {
        let y = <SwaggerException>x;
        ....
   }

is this ok for you all?

I don’t recommend using instanceof here (or almost anywhere) for type detection like this - it’s very brittle and makes assumptions about where this code will run. Anywhere multiple windows/contexts are used (IFrame, etc.) will fail this check, see the rationale behind Array.isArray for example…

If this is necessary, I would add a property to SwaggerException that can be used to test whether it’s a SwaggerException or not, and a corresponding static method to the SwaggerException class that tests this property. This is the same idea as Array.isArray.

For example, SwaggerException.isSwaggerException(err) where isSwaggerException checks for the existence of some property and value on the object.

The test could use a property added to every instance like public _type = "SWAGGER_EXCEPTION" (the underscore to let people know not to do this check directly). Then the check becomes public static isSwaggerException(error: any) { return error._type && error._type === "SWAGGER_EXCEPTION"; }