Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Errors thrown in angular 6 resolver lose error custom type

I'm trying to throw custom errors in my resolvers that I catch with my global error handler. I can throw errors in a component and they come through fine, but when I throw them in the resolver their type is changed to the standard Error type.

Here is a functioning repro: https://stackblitz.com/edit/angular-gitter-vvgys6

Setup

class DisplayableError extends Error {
// ...
}


@Injectable()
export class GlobalErrorHandlerService {
  constructor() { }

  handleError(error) {

    console.log('GOT ERROR instance of DisplayableError', error instanceof DisplayableError);

  }
}

Working usage

in any component I can just throw an error and it's caught in the global error handler and it is an instance of DisplayableError.

throw new DisplayableError('blah');

Broken usage

When I throw the error in the resolver the instance type is changed to Error and instanceof DisplayableError returns false.

@Injectable()
export class StoreGetResolver implements Resolve<StoreModel> {
  constructor(
    private storeService: StoreService,
  ) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<StoreModel> {

    let storeId = route.paramMap.get('storeId');
    return this.storeService.get(storeId)
      .catch(error => Observable.throw(new DisplayableError('my custom error')));
  }

}

I've also tried this

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<StoreModel> {

  let storeId = route.paramMap.get('storeId');
  return this.storeService.get(storeId)
    .do(
      () => { },
      error => throw new DisplayableError('my custom error')
    );
}

...and even this

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<StoreModel> {
  throw new DisplayableError('my custom error');

}

The constructor for DisplayableError is called with the correct data and the message even makes it to the global error handler, but the the error is of type Error instead of DisplayableError when it gets there

like image 771
Lenny Avatar asked Jul 25 '18 00:07

Lenny


1 Answers

This is a known issue with Typescript: https://github.com/Microsoft/TypeScript/issues/13965

The workaround is to do some fiddling with the prototype:

// Use this class to correct the prototype chain.
export class MyError extends Error {
    __proto__: Error;
    constructor(message?: string) {
        const trueProto = new.target.prototype;
        super(message);

        // Alternatively use Object.setPrototypeOf if you have an ES6 environment.
        this.__proto__ = trueProto;
    }
}
like image 152
joh04667 Avatar answered Oct 13 '22 07:10

joh04667