Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript 2.1+ and Errors #2612

Closed
benlesh opened this issue May 24, 2017 · 8 comments
Closed

TypeScript 2.1+ and Errors #2612

benlesh opened this issue May 24, 2017 · 8 comments
Assignees

Comments

@benlesh
Copy link
Member

benlesh commented May 24, 2017

Issue

Currently, we're extending Error to create the ability to do instanceof checks again things like ObjectUnsubscribedError. This is no longer something that TypeScript supports for a variety of principled reasons.

Proposed Change

We move to just throwing simple new Error(), but decorating that error with a custom property, and providing a method to check that property. Ideally, that property will be set with a Symbol to avoid collisions.

const timeoutErrorMsg = 'RxJS Timeout Error';
const timeoutErrorSymbol = Symbol(timeoutErrorMsg);

export function createTimeoutError(): Error {
  const error = new Error(timeoutErrorMsg');
  error[timeoutErrorSymbol] = true;
  return error;
}

export function isTimeoutError(err: Error): boolean {
  return err && err[timeoutErrorSymbol];
}

And then to check an error:

source$
  .timeout(3000)
  .catch(err => {
    if (isTimeoutError(err)) {
      // if it's a timeout error from Rx, handle it in some way
      return Observable.of({ handled: 'timeout error' });
    }
    throw err; // otherwise rethrow
  })

Other Things

We should probably make these utilties available on Rx.Util. for example: Rx.Util.isTimeoutError

This affects the following

  • EmptyError
  • TimeoutError
  • ArgumentOutOfRangeError
  • UnsubscriptionError
  • ObjectUnsubscribedError

This would be a BREAKING CHANGE for sure.

@kwonoj
Copy link
Member

kwonoj commented May 24, 2017

#2582

@kwonoj
Copy link
Member

kwonoj commented May 24, 2017

So we're not considering mutating Error construction to make custom error object backward compatible like proposed at #2582 (comment) ?

@benlesh
Copy link
Member Author

benlesh commented May 24, 2017

FWIW: The Angular team has also gone with the approach I mentioned above. I think it's clean and simple. Sucks that it's breaking, but I think it's time we consider releasing a v6 beta.

@benlesh
Copy link
Member Author

benlesh commented May 24, 2017

@kwonoj ...given that no one's compiler is supporting this, and you'll end up needing to hack around it in ES5 anyhow, we should probably jump on a simple but familiar solution.

@kwonoj
Copy link
Member

kwonoj commented May 24, 2017

I see. Let's see if there's some other opinion as well. /cc @david-driscoll too.

@david-driscoll
Copy link
Member

david-driscoll commented May 24, 2017

I think it makes sense.

We could introduce an interface as well if we need to be able to capture additional information.

Something like...

const timeoutErrorMsg = 'RxJS Timeout Error';
const timeoutErrorSymbol = Symbol(timeoutErrorMsg);

export interface TimeoutError extends Error { hello: string; }

export function createTimeoutError(): TimeoutError {
  const error = new Error(timeoutErrorMsg);
  error[timeoutErrorSymbol] = true;
  return <any>error;
}

export function isTimeoutError(err: Error): err is TimeoutError {
  return err && err[timeoutErrorSymbol];
}

@felixfbecker
Copy link
Contributor

felixfbecker commented Oct 16, 2017

A symbol sounds unnecessarily complex for this. Every other Error in NodeJS just has a code property with known string error codes that can be checked against. Every native error in the browser has a name property. E.g. you can check the error of a fetch like if (err.name === 'AbortError'). To me it is more intuitive to check if name is a specific error code than to check if a certain symbol property is set to true.

Another option is to transpile TypeScript's ES6 output with Babel, which gets the inheritance right. That said, error codes are always a better idea, because any check should work no matter from what version of rxjs the error came from, which is not true for instanceof. Assert on interfaces, not implementations.

@benlesh
Copy link
Member Author

benlesh commented Aug 20, 2020

We're well past this now.

@benlesh benlesh closed this as completed Aug 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants