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:
first
operator explicitly, e.g. import 'rxjs/add/operator/first'
. This does not change the error.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:
Your understanding that a Subject is also an Observable is correct but to an extent that a Subject can also be used as an Observable. But that doesn't make a Subject
an Observable
and vice versa.
As suggested by ggradnig you should be changing the return type of your confirm
function to Observable<boolean>
instead of Subject<boolean>
since the first
method on the Subject<boolean>
would return an Observable<boolean>
import { Subject } from 'rxjs'
export class Example {
public response$: Subject < boolean > ;
public confirm(prompt: string): Observable<boolean> {
// ...set up a confirmation dialog...
this.response$ = new Subject < boolean > ();
return this.response$.first();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With