While working at REDACTED, I reported the following issue.
There is a little bug in our Core module which causes no harm at run time but is nonetheless very annoying because it defeats the purpose of using TypeScript instead of JavaScript, which is type matching. Given that the code editors we use support completion suggestions based on type declarations and type inference, it’s a real pity to loose those benefits because of that mosquito.
All of our access to Back end endpoints passes through copy-paste-adapted TypeScript methods whose return type is always set to something like this:
someEndpoint(params: ...): Observable<Response | OperationFailure> {
// ...
}
while it should be
someEndpoint(params: ...): Observable<Response> {
// ...
}
In fact, the omitted body of someEndpoint
properly converts an HTTP response into an object of type Observable, but a success response is transformed into a Response
type object and that is returned on the next
channel of the observable, while a failure response is transformed into an OperationFailure
type object and that is returned on the error
channel of the observable.
Given that the ReactiveX code we use is programmed like this:
rxjs/src/internal/Observable.ts
export class Observable<T> implements Subscribable<T> {
export interface Subscribable<T> {
subscribe(observerOrNext?: PartialObserver<T> | ((value: T) => void),
error?: (error: any) => void,
complete?: () => void): Unsubscribable;
}
the expression Observable<T>
means Observable whose ‘next’ values’ type is T. Hence, the return type of someEndpoint
should be Observable<Response>
instead of Observable<Response | OperationFailure>
.
This fix would allow not only to improve code completion when programming services for accessing endpoints, but it would also avoid having to either cast values to their intended type or use values of type any
just to keep the TypeScript compiler happy. Given that using values of type any
is easier than casting them to their intended type, we now have mostly unchecked responses.