Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Strongly type Observable Error #2646

Closed
abdulkareemnalband opened this issue Jun 7, 2017 · 7 comments
Closed

Strongly type Observable Error #2646

abdulkareemnalband opened this issue Jun 7, 2017 · 7 comments
Labels
TS Issues and PRs related purely to TypeScript issues

Comments

@abdulkareemnalband
Copy link

RxJS version: [email protected]

Code to reproduce: none

Expected behavior: Observable<T,E> should be used for definition where E tell type of error to be expected

Actual behavior: Observable<T> where error is typed as any

Additional information: Typescript 2.3 provide default type for generics using that we can have Observable<T,E=any> for backward compability

@kwonoj kwonoj added TS Issues and PRs related purely to TypeScript issues type: discussion labels Jun 7, 2017
@felixfbecker
Copy link
Contributor

I disagree. TypeScript does not have error types.
In Java, thrown error types are part of the interface contract, declared with throws. This does not exist in TypeScript, only the return type is part of the interface contract. The error type could be anything if you call other functions, so you should do runtime type checking, like checking for an error code.
Consequently, Promises don't have an error type, and Observables shouldn't either.

@hrajchert
Copy link

hrajchert commented Jan 12, 2018

You could use Observable.throw to help type errors. Promises have the same problem, thats why I created Task

@alexandercarls
Copy link

Here is a use case I often run into:

  put<T>(path: string, body = {}): Observable<T> {
    return this.http
      .put<T>(`${environment.apiUrl}${path}`, JSON.stringify(body), {
        headers: this.setHeaders(),
      }).pipe(
        catchError((err: HttpErrorResponse) => throwError(new DomainError(err.error.message)))
      );
  }

In this example code the intention is that I want to translate the HTTP error to my specific domain error.

The caller of the put wrapper can therefore expect either a value of type T or an error of type DomainError. However the error is typed as never/any.

Also note that I had to type the error as HttpErrorResponse otherwise the "HttpClient" from Angular would type it as any even though from the documentation I imagine that the intention was a typed error but they had no way to type it.

@kyranjamie
Copy link

Was about to make an issue, but this seems close enough...

It'd be great if throwError accepted a type argument. At present, the first argument of throwError is any. (Gitter discussion).

Our use case is simple. A trading platform where an order can either succeed or fail. If it fails, we want to terminate the stream, update the UI etc.

Consider this example:

// order.service.ts
submitOrder (order) { // implicitly Observable<Order>

  return this.http.post<Order>(order).pipe(

    // switch to stream of order events
    switchMap(orderId => this.orderEvents$.pipe(filterById(orderId)),

    // throw error if order fails
    switchMap(order => order.status === 'error' ? throwError(order) : of(order))
  );
}
// some-component.ts
this.service.submitOrder(order).subscribe(
  successfulOrder => { ... },   // implictly type as `Order`
  failedOrder => { ... }        // typed as `any`
);

Were throwError to accept type arg:

switchMap(order => order.status === 'error' ? throwError<Order>(order) : of(order))

...we would have implicit typing. Without the need to coerce the type in each case of submitOrders usage.

@cartant
Copy link
Collaborator

cartant commented Jun 13, 2018

@kyranjamie Strongly typing throwError still wouldn't allow the error in the subscribe callback to be typed differently. See Felix's comment above. If the type declarations for the error callback in subscribe are to be changed at all, they should be changed to unknown - when that top level type becomes available - because that's what they are.

@felixfbecker
Copy link
Contributor

Btw, the equivalent issue in TypeScript is microsoft/TypeScript#13219. If we ever get that issue (declarations for exceptions a function can throw), Promise would be changed to have an error type, and then Observable should be changed too. Until then, rxjs should stay consistent with how TypeScript treats synchronous exceptions and Promise rejections (including, the error type should only become unknown if promise.catch() changes any to unknown).

@Drundia
Copy link

Drundia commented Mar 17, 2020

@felixfbecker This is an interesting point, however the developer can assert the type of observable errors and promise rejections, yet cannot specify these assertions as type parameters, while TypeScript could enforce that type contract in subscribers. TS cannot enforce that type on the provider side, but do two wrongs make it right?

I understand that the final error is a union of all possible errors in the chain (whether it's JS stack, Promise chain, Observable operator chain), so probably every then and every operator could convert error type to any, but being able to assert the error type in a final constructed Observable would be absolutely great and it doesn't require syntax additions to TS to specify possible function throws.

@benlesh benlesh closed this as completed May 4, 2021
@ReactiveX ReactiveX locked and limited conversation to collaborators May 4, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
TS Issues and PRs related purely to TypeScript issues
Projects
None yet
Development

No branches or pull requests

9 participants