angularfire: Interface 'DatabaseSnapshotExists' incorrectly extends interface 'DataSnapshot'

Version info

Angular: 14.1.1

Firebase: 9.9.2

AngularFire: 7.4.1

Other (e.g. Ionic/Cordova, Node, browser, operating system):

How to reproduce these conditions

Failing test unit, Stackblitz demonstrating the problem https://github.com/wojteko22/angular-fire-bug

Steps to set up and reproduce

  1. Clone repo
  2. npm install
  3. ng serve

Sample data and security rules

Debug output

** Errors in the JavaScript console **

Error: node_modules/@angular/fire/compat/database/interfaces.d.ts:47:18 - error TS2430: Interface 'DatabaseSnapshotExists<T>' incorrectly extends interface 'DataSnapshot'.
  Types of property 'forEach' are incompatible.
    Type '(action: (a: DatabaseSnapshot<T>) => boolean) => boolean' is not assignable to type '(action: (a: DataSnapshot & { key: string; }) => boolean | void) => boolean'.
      Types of parameters 'action' and 'action' are incompatible.
        Types of parameters 'a' and 'a' are incompatible.
          Type 'DatabaseSnapshot<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
            Type 'DatabaseSnapshotExists<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
              Type 'DatabaseSnapshotExists<T>' is not assignable to type 'DataSnapshot'.
                Types of property 'forEach' are incompatible.
                  Type '(action: (a: DatabaseSnapshot<T>) => boolean) => boolean' is not assignable to type '(action: (a: DataSnapshot & { key: string; }) => boolean | void) => boolean'.
                    Types of parameters 'action' and 'action' are incompatible.
                      Types of parameters 'a' and 'a' are incompatible.
                        Type 'DatabaseSnapshot<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
                          Type 'DatabaseSnapshotDoesNotExist<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
                            Type 'DatabaseSnapshotDoesNotExist<T>' is not assignable to type '{ key: string; }'.
                              Types of property 'key' are incompatible.
                                Type 'string | null' is not assignable to type 'string'.
                                  Type 'null' is not assignable to type 'string'.

47 export interface DatabaseSnapshotExists<T> extends firebase.database.DataSnapshot {
                    ~~~~~~~~~~~~~~~~~~~~~~


Error: node_modules/@angular/fire/compat/database/interfaces.d.ts:52:18 - error TS2430: Interface 'DatabaseSnapshotDoesNotExist<T>' incorrectly extends interface 'DataSnapshot'.
  Types of property 'forEach' are incompatible.
    Type '(action: (a: DatabaseSnapshot<T>) => boolean) => boolean' is not assignable to type '(action: (a: DataSnapshot & { key: string; }) => boolean | void) => boolean'.
      Types of parameters 'action' and 'action' are incompatible.
        Types of parameters 'a' and 'a' are incompatible.
          Type 'DatabaseSnapshot<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
            Type 'DatabaseSnapshotDoesNotExist<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
              Type 'DatabaseSnapshotDoesNotExist<T>' is not assignable to type 'DataSnapshot'.
                Types of property 'forEach' are incompatible.
                  Type '(action: (a: DatabaseSnapshot<T>) => boolean) => boolean' is not assignable to type '(action: (a: DataSnapshot & { key: string; }) => boolean | void) => boolean'.
                    Types of parameters 'action' and 'action' are incompatible.
                      Types of parameters 'a' and 'a' are incompatible.
                        Type 'DatabaseSnapshot<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
                          Type 'DatabaseSnapshotExists<T>' is not assignable to type 'DataSnapshot & { key: string; }'.
                            Type 'DatabaseSnapshotExists<T>' is not assignable to type '{ key: string; }'.
                              Types of property 'key' are incompatible.
                                Type 'string | null' is not assignable to type 'string'.
                                  Type 'null' is not assignable to type 'string'.

52 export interface DatabaseSnapshotDoesNotExist<T> extends firebase.database.DataSnapshot {
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

** Output from firebase.database().enableLogging(true); **

** Screenshots **

Expected behavior

No error in console

Actual behavior

Error in console

Reason

The reason of this error is change of forEach() signature of firebase.database.DataSnapshot in firebase@9.9.2

These are interfaces from @angular/fire:

export interface DatabaseSnapshotExists<T> extends firebase.database.DataSnapshot {
    exists(): true;
    val(): T;
    forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
}
export interface DatabaseSnapshotDoesNotExist<T> extends firebase.database.DataSnapshot {
    exists(): false;
    val(): null;
    forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
}

In firebase@9.9.2 firebase.database.DataSnapshot has such method:

forEach(
  action: (
    a: firebase.database.DataSnapshot & { key: string }
  ) => boolean | void
): boolean;

In firebase@9.9.1 it was:

forEach(
  action: (a: firebase.database.DataSnapshot) => boolean | void
): boolean;

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 16
  • Comments: 46 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Firebase: 9.9.2

I solved the issue by modifying this file like this:

[my project path]\node_modules\@angular\fire\compat\database\interfaces.d.ts

export interface DatabaseSnapshotExists<T> extends firebase.database.DataSnapshot {
  exists(): true;
  val(): T;
  // forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
  forEach(action: (a: firebase.database.DataSnapshot & { key: string }) => boolean | void): boolean;
}
export interface DatabaseSnapshotDoesNotExist<T> extends firebase.database.DataSnapshot {
  exists(): false;
  val(): null;
  // forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
  forEach(action: (a: firebase.database.DataSnapshot & { key: string }) => boolean | void): boolean;
}

Then, I was able to read/write to the Firebase “Realtime Database”.

Problem still occurs. I’ve set skipLibcheck in the tsconfig.json to avoid checking libraries. But it’s just a temporary hack to ignore errors.

"skipLibCheck": true

Same issue, using angular 15.0.0 - seems to be an issue with compatibility interfaces @angular/fire/compat/firestore/interfaces.d.ts.

This is momentarily fixed by changing the above file, replacing line numbers 15 and 24 to:

data(options?: SnapshotOptions): any;

SOLUTION angular/fire 7.5.0 firebase 9.16.0 go to interfaces.d.ts the file that generates the error add at the end of the error row <T> export interface QueryDocumentSnapshot<T> extends firebase.firestore.QueryDocumentSnapshot<T> do for all 3 errors

The problem is solved with firebase@9.9.3 firebase.database.DataSnapshot again has method:

forEach(
  action: (a: firebase.database.DataSnapshot) => boolean | void
): boolean;

instead of

forEach(
  action: (
    a: firebase.database.DataSnapshot & { key: string }
  ) => boolean | void
): boolean;

as in firebase@9.9.2

This resolves the problem for local build, but would not solve the problem on CD/CI environment builds. Hopefully a more permanent solution is in the works.

Have this problem too. Currently setting "skipLibCheck": true seems the best option. It’s always fun with AngularFire.

Same issue

@angular/core”: “^15.0.0”, “@angular/fire”: “^7.5.0”, “firebase”: “^9.14.0”, “typescript”: “~4.8.4”

used the previously mentioned temp fix

“skipLibCheck”: true -> tsconfig.json

It compiles but not sure if it works.

UPDATE I’ve given up. Rebuilding my app as a React Native app and having wonderful success. My recommendation, bite the bullet, learn react and throw this garbage angular fire in the trash. Then empty the trash.

Same issue here with Angular 15, any updates on this?

Same here Temporarily solution for me: Downgrade typescript to 4.7.4

Firebase: 9.9.2

I solved the issue by modifying this file like this:

[my project path]\node_modules\@angular\fire\compat\database\interfaces.d.ts

export interface DatabaseSnapshotExists<T> extends firebase.database.DataSnapshot {
  exists(): true;
  val(): T;
  // forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
  forEach(action: (a: firebase.database.DataSnapshot & { key: string }) => boolean | void): boolean;
}
export interface DatabaseSnapshotDoesNotExist<T> extends firebase.database.DataSnapshot {
  exists(): false;
  val(): null;
  // forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
  forEach(action: (a: firebase.database.DataSnapshot & { key: string }) => boolean | void): boolean;
}

Then, I was able to read/write to the Firebase “Realtime Database”.

The problem about this is: I can’t use that workaround in production because CI/CD pipeline. 😔

Hi! I have the same issue. I am actually using the following version :

  • Angular v16.0.3
  • Typescript v5.0.4
  • Firebase v9.22.2
  • AngularFire v7.6.1

I hade the following, in tsconfig : “skipLibCheck”: true

as suggest by @igor-augustynski-furba

It works.

Same issue, using angular 15.0.0 - seems to be an issue with compatibility interfaces @angular/fire/compat/firestore/interfaces.d.ts.

This is momentarily fixed by changing the above file, replacing line numbers 15 and 24 to:

data(options?: SnapshotOptions): any;

Is it worth doing a PR for this? It resoled my issue too.

The only way I could make this work was by setting compilerOptions.strict (tsconfig.json) to “false”. Does anyone have a better idea? I suppose it’s a problem in the fire library itself and unless that is fixed in there, there is not much we can do?

A Big stop for the project.

@angular/core”: “^15.0.0”, “firebase”: “^9.15.0”, “@angular/fire”: “^7.5.0”, “typescript”: “~4.8.2”

For me this happened when using the newer firestorm (from ‘@angular/fire/firestore’), while also importing the compat firestorm somewhere (from "@angular/fire/compat/firestore). For me to solution was to only ever use one of the two in my project.

This fixed it for me Firebase introduced a modular SDK with v9, which is tree-shakeable, and therefore, more efficient in terms of bundle size. @angular/fire followed this change by providing a way to use both the older and the newer versions, using @angular/fire/compat for the older version.

Use your IDE’s search functionality to find all instances where you’re importing from @angular/fire/compat/firestore. If you’ve decided to use the newer SDK, replace these with @angular/fire/firestore.

For example in the app.module,ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

// Modern Angular Fire imports
import { provideFirebaseApp, getApp, initializeApp } from '@angular/fire/app';
import { getFirestore, provideFirestore } from '@angular/fire/firestore';
import { getAuth, provideAuth } from '@angular/fire/auth';
import { getStorage, provideStorage } from '@angular/fire/storage';
import { getDatabase, provideDatabase } from '@angular/fire/database';

import { AngularMaterialModule } from './modules/angular-material.module';
import { AppRoutingModule } from './modules/app-routing.module';

import { environment } from '../environments/environment';

import { AppComponent } from './app.component';
import { HelloWorldComponent } from './pages/hello-world/hello-world.component';
import { CoreComponent } from './pages/core/core.component';

@NgModule({
  declarations: [
    AppComponent,
    HelloWorldComponent,
    CoreComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AngularMaterialModule,
    
    // Firebase Initialization
    provideFirebaseApp(() => initializeApp(environment.firebaseConfig)),
    provideAuth(() => getAuth()),
    provideFirestore(() => getFirestore()),
    provideStorage(() => getStorage()),
    provideDatabase(() => getDatabase())
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now, when you want to use Firestore, Auth, or any other Firebase service in your components or services, you’d inject them using Angular’s DI system. For example, with Firestore:

import { Component, OnInit } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore'; // This import will remain the same for convenience

@Component({
  selector: 'app-some-component',
  template: `...`,
  styleUrls: ['...']
})
export class SomeComponent implements OnInit {
  constructor(private firestore: AngularFirestore) {}

  ngOnInit() {
    // Use this.firestore here
  }
}
 

Angular 15 dosen’t with any version of firebase, as a hack u can change “strict” to false in tsconfig.json file. Team please fix this

i am facing same problem here

@angular/fire”: “^7.6.1”, “@angular/core”: “^16.0.0”,

I don’t like it but for the moment i did:

“skipLibCheck”: true

and it works.

For me this happened when using the newer firestorm (from ‘@angular/fire/firestore’), while also importing the compat firestorm somewhere (from "@angular/fire/compat/firestore). For me to solution was to only ever use one of the two in my project.

Same issue, using angular 15.0.0 - seems to be an issue with compatibility interfaces @angular/fire/compat/firestore/interfaces.d.ts. This is momentarily fixed by changing the above file, replacing line numbers 15 and 24 to:

data(options?: SnapshotOptions): any;

Is it worth doing a PR for this? It resoled my issue too.

It works, but if I use firebase hosting, I get error due of this and I cant build project and deploy it only if to deploy it by hands

I have "firebase": "^9.14.0", and the issue is still there

I’ve run into this error and couldn’t find the solution anywhere so I tried to fix it myself and I’ve managed to get rid of the errors but not sure if this will break firestore… Please check.

Since the error was saying that the “docs” was the problem, I commented it out for both of them:

export interface QuerySnapshot<T> extends firebase.firestore.QuerySnapshot {
    // readonly docs: QueryDocumentSnapshot<T>[];
}
export interface DocumentChange<T> extends firebase.firestore.DocumentChange<DocumentData> {
    // readonly doc: QueryDocumentSnapshot<T>;
}

and for line 13 and 22, I changed

 firebase.firestore.DocumentSnapshot 
to 
firebase.firestore.DocumentData 

instead for both of them and all errors went away.

Does anyone know if this is ok or not?