Angularfire: valueChanges() loses type information

Created on 22 Oct 2017  路  8Comments  路  Source: angular/angularfire

Using [email protected].

Calling .valueChanges() on an AngularFireObject<T> should return an Observable<T | null>, but instead returns Observable<{} | null>.

Similarly, calling .valueChanges() on an AngularFireList<T> should return an Observable<T[]>, but instead returns Observable<{}[]>.

This results in error messages for code that should be correct. For example, the following code:

interface FooBar {
    foo: string;
    bar: number;
}
afDb.object<FooBar>("/foo-bar/1")
    .valueChanges()
    .subscribe(fooBarItem => {
        if (fooBarItem !== null) {
            console.log(`Foo: ${fooBarItem.foo}, Bar:${fooBarItem.bar}`);
        }
    });

afDb.list<FooBar>("/foo-bar")
    .valueChanges()
    .subscribe(fooBarArray => {
        fooBarArray.forEach(fooBarItem => {
            console.log(`Foo: ${fooBarItem.foo}, Bar:${fooBarItem.bar}`);
        });
    });

yields the following TypeScript errors on the console.log() statements:

Property 'foo' does not exist on type '{}'. 
Property 'bar' does not exist on type '{}'. 
Property 'foo' does not exist on type '{}'. 
Property 'bar' does not exist on type '{}'. 

I think fixing this problem is simply a matter of setting the return type explicitly for the .valueChanges() function.

Most helpful comment

i think a more elegant workaround until this gets fixed would be to explicitly cast the output of .valueChanges() to your desired type

(afDb.object<FooBar>("/foo-bar/1")
    .valueChanges() as Observable<FooBar>)
    .subscribe(fooBarItem => {
        if (fooBarItem !== null) {
            console.log(`Foo: ${fooBarItem.foo}, Bar:${fooBarItem.bar}`);
        }
    });

(afDb.list<FooBar>("/foo-bar")
    .valueChanges() as Observable<FooBar[]>)
    .subscribe(fooBarArray => {
        fooBarArray.forEach(fooBarItem => {
            console.log(`Foo: ${fooBarItem.foo}, Bar:${fooBarItem.bar}`);
        });
    });

All 8 comments

Could this be related to why I'm getting this error on building?
`Property 'valueChanges' does not exist on type 'FirebaseListObservable

  L24:    constructor(public navCtrl: NavController, public navParams: NavParams, public viewCtrl: ViewController, afDB: AngularFireDatabase) {
  L25:      this.items = afDB.list('snippets'+this.title).valueChanges();`

Error: Failed to transpile program at new BuildError (/Users/sr/Ionic/http/node_modules/@ionic/app-scripts/dist/util/errors.js:16:28) at /Users/sr/Ionic/http/node_modules/@ionic/app-scripts/dist/transpile.js:137:20 at transpileWorker (/Users/sr/Ionic/http/node_modules/@ionic/app-scripts/dist/transpile.js:103:12) at Object.transpile (/Users/sr/Ionic/http/node_modules/@ionic/app-scripts/dist/transpile.js:61:12) at buildProject (/Users/sr/Ionic/http/node_modules/@ionic/app-scripts/dist/build.js:97:78) at /Users/sr/Ionic/http/node_modules/@ionic/app-scripts/dist/build.js:47:16

@TheShashank, your error is due to versioning issues and unrelated to my issue. In previous versions afdb.list() returns a FirebaseListObservable, but with version 5 the new API returns an AngularFireList. .valueChanges() is a method of AngularFireList. You seem to be attempting to use the version 5 API but running version 4. Check you package.json and update to the latest version and your error should go away.

@jaufgang - thanks for the reply. So that error did indeed go away - you seem to be right about the versioning. However, now I have a new issue about 'browser' not containing a valid alias configuration. Would you possibly know anything about that?

No, please post that as a separate issue.

I'm having this issue as well. Right now it doesn't disrupt anything in the application, but it triggers a tslint error in my console.

had to set the return type to any to get it to stop complaining -_-

Despite creating a complete interface that reflected my database... I had to add [propName: string]: any; to my interface to get it to stop complaining.. pretty ugly stuff.

i think a more elegant workaround until this gets fixed would be to explicitly cast the output of .valueChanges() to your desired type

(afDb.object<FooBar>("/foo-bar/1")
    .valueChanges() as Observable<FooBar>)
    .subscribe(fooBarItem => {
        if (fooBarItem !== null) {
            console.log(`Foo: ${fooBarItem.foo}, Bar:${fooBarItem.bar}`);
        }
    });

(afDb.list<FooBar>("/foo-bar")
    .valueChanges() as Observable<FooBar[]>)
    .subscribe(fooBarArray => {
        fooBarArray.forEach(fooBarItem => {
            console.log(`Foo: ${fooBarItem.foo}, Bar:${fooBarItem.bar}`);
        });
    });
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Leanvitale picture Leanvitale  路  3Comments

KLiFF2606 picture KLiFF2606  路  3Comments

martinyoussef picture martinyoussef  路  3Comments

itisparas picture itisparas  路  3Comments

fisherds picture fisherds  路  3Comments