angular / angularfire

Angular + Firebase = ❀️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.69k stars 2.19k forks source link

Build error: This module is declared with using 'export =' #2635

Closed akshaybabloo closed 4 years ago

akshaybabloo commented 4 years ago

After updating to v6.0.4 from v6.0.3 I am getting the following error - This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.

Setting allowSyntheticDefaultImports: true gives the following error:

ERROR in node_modules/@angular/fire/storage/observable/fromTask.d.ts:3:83 - error TS2694: Namespace 'firebase' has no exported member 'default'.

3 export declare function fromTask(task: UploadTask): Observable<import("firebase").default.storage.UploadTaskSnapshot>;
                                                                                    ~~~~~~~

Version info

Angular:

10.2.1

Firebase:

7.24.0

AngularFire:

6.0.4

How to reproduce these conditions

Steps to set up and reproduce

Update to 6.0.4

Debug output

N/A

Log stack

ERROR in node_modules/@angular/fire/firebase.app.module.d.ts:2:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    2 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/auth-guard/auth-guard.d.ts:4:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    4 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/auth/auth.d.ts:4:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    4 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/auth/auth.d.ts:12:14 - error TS2411: Property 'authState' of type 'Observable<any>' is not assignable to string index type 'Promise<any> & ((...args: unknown[]) => Promise<any>) & ((...args: unknown[]) => any)'.

    12     readonly authState: Observable<firebase.User | null>;
                    ~~~~~~~~~
    node_modules/@angular/fire/auth/auth.d.ts:16:14 - error TS2411: Property 'idToken' of type 'Observable<string>' is not assignable to string index type 'Promise<any> & ((...args: unknown[]) => Promise<any>) & ((...args: unknown[]) => any)'.

    16     readonly idToken: Observable<string | null>;
                    ~~~~~~~
    node_modules/@angular/fire/auth/auth.d.ts:20:14 - error TS2411: Property 'user' of type 'Observable<any>' is not assignable to string index type 'Promise<any> & ((...args: unknown[]) => Promise<any>) & ((...args: unknown[]) => any)'.

    20     readonly user: Observable<firebase.User | null>;
                    ~~~~
    node_modules/@angular/fire/auth/auth.d.ts:26:14 - error TS2411: Property 'idTokenResult' of type 'Observable<any>' is not assignable to string index type 'Promise<any> & ((...args: unknown[]) => Promise<any>) & ((...args: unknown[]) => any)'.

    26     readonly idTokenResult: Observable<firebase.auth.IdTokenResult | null>;
                    ~~~~~~~~~~~~~
    node_modules/@angular/fire/firestore/interfaces.d.ts:2:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    2 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/firestore/collection/collection.d.ts:2:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    2 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/firestore/document/document.d.ts:5:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    5 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/firestore/collection-group/collection-group.d.ts:2:8 - [39m[91merror TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    2 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/firestore/firestore.d.ts:9:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    9 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/storage/interfaces.d.ts:1:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    1 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/storage/storage.d.ts:6:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    6 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/storage/observable/fromTask.d.ts:3:83 - error TS2694: Namespace 'firebase' has no exported member 'default'.

    3 export declare function fromTask(task: UploadTask): Observable<import("firebase").default.storage.UploadTaskSnapshot>;
                                                                                        ~~~~~~~
    node_modules/@angular/fire/analytics/analytics.d.ts:3:8 - error TS1259: Module '"/Users/akshayrajgollahalli/Documents/GitHub/lectus-ui/node_modules/firebase/index"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

    3 import firebase from 'firebase/app';
             ~~~~~~~~

      node_modules/firebase/index.d.ts:9710:1
        9710 export = firebase;
             ~~~~~~~~~~~~~~~~~~
        This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.
    node_modules/@angular/fire/analytics/analytics.d.ts:17:5 - error TS2411: Property 'updateConfig' of type '(config: Config) => Promise<void>' is not assignable to string index type 'Promise<any> & ((...args: unknown[]) => Promise<any>) & ((...args: unknown[]) => any)'.

    17     updateConfig(config: Config): Promise<void>;
           ~~~~~~~~~~~~
Soolan commented 4 years ago

@akshaybabloo I'm experiencing the same issue after upgrade:

    "@angular/core": "~10.2.1",
    "@angular/fire": "^6.0.4",
    "firebase": "^8.0.0",
    "firebaseui": "^4.7.1",
    // other packages

I left firebaseui there to point out that I was using it as a simple and quick way for authentication. What a mistake! Turned out it has issues and not mature enough to be used in production.

So if by any chance you are using that, or any 3rd party package that relies on firebase or angular/fire, (i.e. firestore dependencies) temporarily disable them and see if that resolves the issue.

It doesn't fix the problem but for me it helped me to narrow down the issue. Hope it shed some light on the issue.

Technical debt of any sort (official firebaseui included) is bad.

akshaybabloo commented 4 years ago

@Soolan This is what I have


 "dependencies": {
    "@angular/animations": "~10.2.1",
    "@angular/cdk": "^10.2.6",
    "@angular/common": "~10.2.1",
    "@angular/compiler": "~10.2.1",
    "@angular/core": "~10.2.1",
    "@angular/fire": "^6.0.3",
    "@angular/forms": "~10.2.1",
    "@angular/material": "^10.2.6",
    "@angular/platform-browser": "~10.2.1",
    "@angular/platform-browser-dynamic": "~10.2.1",
    "@angular/router": "~10.2.1",
    "@types/file-saver": "^2.0.1",
    "@types/papaparse": "^5.2.4",
    "bootstrap": "^4.5.3",
    "file-saver": "^2.0.2",
    "firebase": "^7.24.0",
    "highcharts": "^8.2.2",
    "highcharts-angular": "^2.8.2",
    "moment": "^2.29.1",
    "ngx-order-pipe": "^2.1.1",
    "papaparse": "^5.3.0",
    "rxjs": "~6.6.3",
    "tslib": "^2.0.3",
    "uppy": "^1.22.0",
    "zone.js": "~0.10.3"
  },
  "devDependencies": {
    "@angular-devkit/architect": ">= 0.900 < 0.1100",
    "@angular-devkit/build-angular": "~0.1002.0",
    "@angular/cli": "~10.2.0",
    "@angular/compiler-cli": "~10.2.1",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^14.14.6",
    "codelyzer": "^6.0.1",
    "firebase-tools": "^8.14.1",
    "fuzzy": "^0.1.3",
    "inquirer": "^7.3.3",
    "inquirer-autocomplete-prompt": "^1.3.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~6.0.0",
    "karma": "~5.2.3",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.1",
    "karma-jasmine-html-reporter": "^1.5.0",
    "open": "^7.3.0",
    "protractor": "~7.0.0",
    "ts-node": "~9.0.0",
    "tslint": "~6.1.3",
    "typescript": "~4.0.5"
  }

I am not too sure if anything here is depending on angular fire... I guess

Soolan commented 4 years ago

I see...

What happens when you add these entries to compilerOptions in tsconfig?

  "compilerOptions": {
    //....
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  },
Soolan commented 4 years ago

also worth checking...

Do you have this import command: import * as firebase from 'firebase/app'

anywhere in your components, services, ...?

Soolan commented 4 years ago

Ok I did a bit of digging and it seems the problem is not the angularfire rather the firebase library itself.

if you need to import firebase anywhere into your angularfire project, the firease.[whatever] is not accessible in the new versions anymore. The path has changed but it seems guys @Google forgot to update the documentations.

Here is an example. Let's say you have this in your imports: import * as firebase from 'firebase/app';

Now if you try to access anything inside firebase as usual it will throw the error messages you shared above. For example this: return firebase.firestore.FieldValue.serverTimestamp()

will return an error. You have to add default to the namespace - in firebase 7.x.x and 8.x.x - in order to make it work:

return firebase.default.firestore.FieldValue.serverTimestamp();

that applies everywhere you are referring to firebase in your code.

akshaybabloo commented 4 years ago

@Soolan OK, I will give this a try. How come it broke now?

jamesdaniels commented 4 years ago

Ah, sorry, we changed over the imports of Firebase JS SDK to work with v8 and cursory tests showed compatibility w/v7; which allowed us to add compatibility without bumping a major version... I'm guessing this isn't going so smoothly in some environments. I'll give it some more testing.

In the meantime upgrading to Firebase v8 should work. You may have to change your imports but in general v8, which exports ES Modules in the way Angular prefers, works way way way better with Angular 9+

fisherj19 commented 4 years ago

Yeah, no. This doesn't work at all with Firebase v8. Sticking to @angular/fire 6.0.3 and firebase 7.24.0 until things can compile again. Angular CLI can't build any of it with the new combo.

akshaybabloo commented 4 years ago

I do have imports like this

import {firestore} from 'firebase/app';
akshaybabloo commented 4 years ago

Yeah, no. This doesn't work at all with Firebase v8. Sticking to @angular/fire 6.0.3 and firebase 7.24.0 until things can compile again. Angular CLI can't build any of it with the new combo.

Yeah me too. But firebase 8 is compatible with v6.0.3

jamesdaniels commented 4 years ago

Firebase v8 doesn't export a namespace anymore, you should use the default export.

import firebase from 'firebase/app'; // don't import { firestore }
firebase.firestore // instead
akshaybabloo commented 4 years ago

OK, I will try that. I think there are a few breaking changes, maybe bumping it to a major release? πŸ€”

jamesdaniels commented 4 years ago

Bumping a major isn't trivial with a library with the popularity of AngularFire, it means there's a very large chance of leaving users behind & unsupported as I only have the resources to support the latest major (on a best-effort basis at that). With a large rewrite of the Firebase JS SDK coming & new Angular majors on the way, I'd rather leave a breaking version for that. Which is why I sometimes do back flips to support multiple Angular/Firebase majors πŸ˜›

mono-sudo commented 4 years ago

Just interested if anyone found some way of getting around the issue? I'm experiencing the same problem :(

akshaybabloo commented 4 years ago

Firebase v8 doesn't export a namespace anymore, you should use the default export.


import firebase from 'firebase/app'; // don't import { firestore }

firebase.firestore // instead

@mono-sudo try this for now, there might be a significant changes to be made. Officially I am not sure.

mono-sudo commented 4 years ago

So maybe I'm being a bit silly. But this is giving me errors. What am I missing? import firebase.firestore from 'firebase/app' doesn't work

akshaybabloo commented 4 years ago

@jamesdaniels any comments on @mono-sudo reply. I haven't tested this yet

jamesdaniels commented 4 years ago

Oh only import firebase from 'firebase/app' and then use firebase.firestore in your code.

ericgopak commented 4 years ago

Setting "allowSyntheticDefaultImports": true under compilerOptions in my tsconfig.json has resolved the issue for me.

My package.json included:

...
    "@angular/fire": "^6.0.4",
    "cordova-plugin-firebase-analytics": "^4.5.0",
    "firebase": "^7.24.0",
...
jamesdaniels commented 4 years ago

Sounds like we got a work-around, closing and pinning since a lot of folk are running into this.

akshaybabloo commented 4 years ago

@ericgopak the problem comes when you upgrade firebase to v8

gbrits commented 4 years ago

Can confirm that @angular/fire 6.0.5 and firebase@8.0.1 no longer receives the error, my solution was simply npm install firebase@latest

DaveA-W commented 4 years ago

+1 same result as @gbrits - all good after upgrade to @angular/fire@6.0.5 and firebase@8.0.1

ericgopak commented 4 years ago

+1 confirm that there's no error with firebase@8.0.1. Since its export = got fixed, adding "allowSyntheticDefaultImports": true to tsconfig.json is no longer needed.

Soolan commented 4 years ago

+1 confirm firebase@8.0.1 works like a charm!

waterplea commented 3 years ago

EDIT: Sorry for pinging you all. It was an issue with TS not picking the new version. After I ctrl+clicked it and fell through it stopped showing the error.

ORIGINAL MESSAGE: I just tried upgrading from @angular/fire@6.0.3 and firebase@7.14.1 to latest (6.1.1 and 8.1.1) and I'm seeing this issue. "allowSyntheticDefaultImports": true helps but reading this thread I'm not sure I'm supposed to do it like that...

vamidi commented 3 years ago

https://firebase.google.com/support/release-notes/js#8.0.0 indeed fixes the issue.

abdel-ships-it commented 3 years ago

I really dislike the proposed fix (allowSyntheticDefaultImports / esModuleInterop ), it feels like a patch. I went on a hunt and figured out a solution that works better for me and might work better for you guys. Before simply copy pasting my code, here is how I came to this fix; if you're not interested just scroll down πŸ‘‡ For those that read this, please point out any potential problems with this approach πŸ‘

If you have a look at the firebase sdk js release notes here you will find the following breaking change

Breaking change: browser fields in package.json files now point to ESM bundles instead of CJS bundles. Users who are using ESM imports must now use the default import instead of a namespace import. Before 8.0.0

import * as firebase from 'firebase/app'

After 8.0.0

import firebase from 'firebase/app'

Code that uses require('firebase/app') or require('firebase') will still work, but in order to get proper typings (for code completion, for example) users should change these require calls to require('firebase/app').default or require('firebase').default. This is because the SDK now uses typings for the ESM bundle, and the different bundles share one typings file.

With this information, I decided to upgrade to firebase v8 (8.2.2) after my upgrade of angular/fire to 6.1.4 despite the recommendation to be on firebase v7.8 in the readme of this repository. I did this because the problem is obviously an importing problem, I decided to change my import statements to match firebase documentation recommendation. Which looks like this import firebase from 'firebase/app';

This introduced the problem of types I was using, as I was importing firestore as a type

// bad
import { firestore } from 'firebase'; // Module '"../../../../../node_modules/firebase"' has no exported member 'firestore'. Did you mean to use 'import firestore from "../../../../../node_modules/firebase"' instead?

const documentRef: firestore.DocumentReference;

The solution is quite simple in retrospect, using the new import and accessing firestore on the firebase global namespace

// good
import firebase from 'firebase/app';

const documentRef: firebase.firestore.DocumentReference;

If you're using the firestore namespace a lot in your code, suffixing it with firebase can be annoying and can reduce readability. To mitigate this I use the following namespace aliasing trick, this will ensure your code changes only affect your import statements. See namespace aliasing in the official typescript documentation here if this syntax is unfamiliar to you

// better
import firebase from 'firebase/app';
import firestore = firebase.firestore;

const documentRef: firestore.DocumentReference;
MahadevanGit commented 3 years ago

Can confirm that @angular/fire 6.0.5 and firebase@8.0.1 no longer receives the error, my solution was simply npm install firebase@latest

+1 same result as @gbrits - all good after upgrade to @angular/fire@6.0.5 and firebase@8.0.1

oguzhan18 commented 2 years ago

@Soolan Thank you so much. When I restarted the project it worked without errors.