Example code, using Angular 4.1.3, rxjs 5.3.0, typescript 2.2.2:
import { Subject } from 'rxjs'
export class Example {
public response$: Subject<boolean>;
public confirm(prompt: string): Subject<boolean> {
// ...set up a confirmation dialog...
this.response$ = new Subject<boolean>();
return this.response$.first();
}
}
When I try to compile this code, typescript complains about the last line:
The 'this' context of type 'Subject<boolean>' is not assignable to method's 'this' of type 'Observable<boolean>'.
Types of property 'lift' are incompatible.
Type '<R>(operator: Operator<boolean, R>) => Observable<boolean>' is not assignable to type '<R>(operator: Operator<boolean, R>) => Observable<R>'.
Type 'Observable<boolean>' is not assignable to type 'Observable<R>'.
Type 'boolean' is not assignable to type 'R'.
My sense is that this is saying that first() is a method of Observable, not Subject, but my understanding is that a Subject is also an Observable, so this should not be a problem. And, in fact, if I ignore the error the code compiles and runs fine.
Things I have tried:
- Various ways of importing the
firstoperator explicitly, e.g.import 'rxjs/add/operator/first'. This does not change the error. - Casting the Subject to an Observable before calling
first(), e.g.return (this.response$ as Observable<boolean>).first();. This results in a different but similar error, which also seems incorrect to me:Type 'Observable<boolean>' is not assignable to type 'Subject<boolean>'. Property 'observers' is missing in type 'Observable<boolean>'.
How can I convince typescript that it is valid to call first() on a Subject?
To clarify in response to the discussion of return types below: the method may also have had an incorrect return type (should be Observable rather than Subject) but that appears to be a separate issue; changing the return type does not resolve the error described above. A further detail confirming this is that when vscode highlights the error, it only highlights this.response$, not the entire return line, suggesting that the problem is between this.response$ and first(), not between first() and the function's signature:
