Skip to content

Observable<never> is not assignable to Subscribable<T> #3891

@felixfbecker

Description

@felixfbecker

Bug Report

Current Behavior

Kinda related to #3890, when trying implement interop by accepting Subscribable as input, you cannot pass Observable<never> into any Subscribable<T>.
This is because Subscribable's signature for subscribe doesn't match that of Observable:

    subscribe(observerOrNext?: PartialObserver<T> | ((value: T) => void), error?: (error: any) => void, complete?: () => void): Unsubscribable;

vs

    subscribe(observer?: PartialObserver<T>): Subscription;
    subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;

So you get this error:

Argument of type 'Observable<never>' is not assignable to parameter of type 'Subscribable<number>'.
  Types of property 'subscribe' are incompatible.
    Type '{ (observer?: NextObserver<never> | ErrorObserver<never> | CompletionObserver<never> | undefined)...' is not assignable to type '(observerOrNext?: NextObserver<number> | ErrorObserver<number> | CompletionObserver<number> | ((v...'.
      Types of parameters 'observer' and 'observerOrNext' are incompatible.
        Type 'NextObserver<number> | ErrorObserver<number> | CompletionObserver<number> | ((value: number) => v...' is not assignable to type 'NextObserver<never> | ErrorObserver<never> | CompletionObserver<never> | undefined'.
          Type '(value: number) => void' is not assignable to type 'NextObserver<never> | ErrorObserver<never> | CompletionObserver<never> | undefined'.
            Type '(value: number) => void' is not assignable to type 'CompletionObserver<never>'.
              Property 'complete' is missing in type '(value: number) => void'.

Reproduction

import { Observable, Subscribable, NEVER } from 'rxjs'

function foo(input: Subscribable<number>) {}

foo(NEVER)

Expected behavior

An Observable that never emits should be assignable to any Observable of any type, since the type doesn't matter if it never emits. This is the semantic of never.

Environment

  • Runtime: any
  • RxJS version: 6.2.1

Possible Solution
Change the signature of Subscribable.subscribe to use an overload, which in my eyes more accurately represents the actual interface.
With the current signature, this is possible, which it shouldn't:

subscribable.subscribe({ error: err => console.log('err 1') }, err => console.log('err 2'))

What would get logged?

Metadata

Metadata

Assignees

No one assigned

    Labels

    TSIssues and PRs related purely to TypeScript issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions