Search code examples
typescriptobserverstypescript-generics

What is R in <R>(observer: Observer<R>) => Subscription | Function | void


The Angularfire2 project has a work-in-progress branch adding a storage feature. Two new files include an Observable class and a Factory function.

Observable class

export class FirebaseUploadTaskObservable<T> extends Observable<T> {

  constructor(
    subscribe?: <R>(observer: Observer<R>) => Subscription | Function | void, 
    public uploadTask?:firebase.storage.UploadTask) {
      super(subscribe);
  }

  lift<T, R>(operator: Operator<T, R>): Observable<R> {
    const observable = new FirebaseUploadTaskObservable<R>();
    observable.source = this;
    observable.operator = operator;
    observable.uploadTask = this.uploadTask;
    return observable;
  }
  ...
}

Factory function

export function FirebaseUploadTaskFactory (uploadTask: UploadTask):
  FirebaseUploadTaskObservable<UploadTaskSnapshot> {

  const obsFunction = (obs: Observer<UploadTaskSnapshot>) => { ... };

  const objectObservable = new FirebaseUploadTaskObservable(obsFunction, uploadTask);

  ...
}

In short, error I'm getting is:

Type 'R' is not assignable to type 'UploadTaskSnapshot'.

This answer helped reinforce what I think I already knew about <T> and generics in Typescript, but what is <R>?

(Full error message)

Argument of type '(obs: Observer) => void' is not assignable to parameter of type '((observer: Observer) => void | Function | Subscription) | undefined'. Type '(obs: Observer) => void' is not assignable to type '(observer: Observer) => void | Function | Subscription'. Types of parameters 'obs' and 'observer' are incompatible. Type 'Observer' is not assignable to type 'Observer'. Type 'R' is not assignable to type 'UploadTaskSnapshot'.


Solution

  • In English, <R>(observer: Observer<R>) => Subscription | Function | void means:

    for any type R, a function that can turn an Observer of R into a Subscription or a function or a nothing

    Now, your constructor has signature constructor(subscribe?: <R>(.... This means it is demanding a function with the properties stated above, i.e. it demands a function that will be happy with an observer of any kind whatsoever. As an example, this constructor will not be satisfied with a:

    const obsFunction = (obs: Observer<UploadTaskSnapshot>) => { ... }
    

    Which in English is a:

    function that takes an Observer<UploadTaskSnapshot> and returns something

    because it isn't a function that will take an observer of R for any type R and like it. This function has a peculiar taste in observers that the constructor is not equipped to accommodate.

    The other answers provide some indication of how to fix the issue, but I believe your <R> parameter might be redundant here. You might just want (observer: Observer<T>).