angular / angularfire

Angular + Firebase = ❤️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.64k stars 2.2k forks source link

Cannot read property 'Timestamp' of undefined. #2124

Closed N-Andronopoulos closed 4 years ago

N-Andronopoulos commented 5 years ago

Bug:

When using aot and build optimizer.

Angular: 7.3.8

Firebase: 6.2.3 (also 5.8.3)

AngularFire: 5.2.1 (also 5.1.3)

How to reproduce these conditions

I have a class file like this:

// noinspection ES6UnusedImports
import * as firebase from 'firebase/app';
import Timestamp = firebase.firestore.Timestamp; // <== Transaction.ts : 9 in the error log.

export class Transaction {
  public date: Date;
  ....
  public greatThingsHere() {
    return Timestamp.fromDate(this.date); // Something like that.
  }
}

If I disable aot and buildoptimizer in angular.json it works again.

Debug output

Uncaught TypeError: Cannot read property 'Timestamp' of undefined
    at Object.1QCC (Transaction.ts:9)
    at i (bootstrap:83)
    at Object.ZJFI (database.service.ts:3)
    at i (bootstrap:83)
    at Object.yxOE (index.ngfactory.js.pre-build-optimizer.js:81)
    at i (bootstrap:83)
    at Module.zUnb (app.component.ts:6)
    at i (bootstrap:83)
    at Object.0 (user-view-routing.module.ts:34)
    at i (bootstrap:83)
grahamtwine commented 4 years ago

try import * as firebase from 'firebase';

LanderBeeuwsaert commented 4 years ago

@grahamtwine If done, firebase will complain you are importing everything, and that you should only do that in development. But yeah, maybe for now that's the best workaround we have.

N-Andronopoulos commented 4 years ago

Well I solved it with:

import * as firebase from 'firebase/app';

export class Transaction {
  public date: Date;
  ....
  public greatThingsHere() {
    return firestore.Timestamp.fromDate(this.date);
  }
}

But I don't why it works. Also I have like the original implementation in an interface and It works there.

import * as firebase from 'firebase/app';
import Timestamp = firebase.firestore.Timestamp;

export interface TransactionModel {
  date: Timestamp;
  ...
}

Well I guess It works there cause its just a symbol for TS compiler.

grahamtwine commented 4 years ago

This is really to do with resolving paths.. Note 'firebase' vs 'firebase/App'

On Thu, 1 Aug 2019 at 18:10, Nikolas Andronopoulos notifications@github.com wrote:

Well I solved it with:

import * as firebase from 'firebase/app';

export class Transaction { public date: Date; .... public greatThingsHere() { return firestore.Timestamp.fromDate(this.date); } }

But I don't why it works. Also I have like the original implementation in an interface and It works there.

import * as firebase from 'firebase/app'; import Timestamp = firebase.firestore.Timestamp;

export interface TransactionModel { date: Timestamp; ... }

Well I guess It works there cause its just a symbol for TS compiler.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/angular/angularfire2/issues/2124?email_source=notifications&email_token=AAGLGSSGXS6SVBWEPCDBW3DQCMDJBA5CNFSM4H34DBIKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3LDI5I#issuecomment-517354613, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGLGSTELC3D7DE2MBV3XCTQCMDJBANCNFSM4H34DBIA .

-- Regards,

Graham Twine +27 82 990 3055

hiepxanh commented 4 years ago

import { Timestamp } from '@firebase/firestore-types'; I think this will be correct, can we close this case? @N-Andronopoulos

beardo01 commented 4 years ago

import { Timestamp } from '@firebase/firestore-types'; I think this will be correct, can we close this case? @N-Andronopoulos

It seems like you are actually unable to use that export at run time.

N-Andronopoulos commented 4 years ago

import { Timestamp } from '@firebase/firestore-types'; I think this will be correct, can we close this case? @N-Andronopoulos

It seems like you are actually unable to use that export at run time.

Use the export at runtime? Its a type... I think its supposed to be only compile time. I think you must use other modules when using Timestamp for functionality. But I may be wrong.

alexandermckay commented 3 years ago

In my case I had not imported firebase/firestore

// Won't work
import firebase from 'firebase/app'
console.log(firebase.firestore.Timestamp.now())

// Will work
import firebase from 'firebase/app'
import 'firebase/firestore'
console.log(firebase.firestore.Timestamp.now())
RRGT19 commented 3 years ago

I have created a file where I have all the imports to make it work, also, I have exported the Timestamp class to make use of it across the application and avoid repeating all the imports again.

// A custom firestore-types.ts
/**
 * To make the Timestamp class to work in a production build,
 * we need to do all these imports.
 *
 * We exported the import to make use of it across the application and avoid
 * repeating all these imports again.
 */

import * as firebase from 'firebase/app';
import 'firebase/firestore';
export import Timestamp = firebase.firestore.Timestamp;

Example of use:

import {Timestamp} from './firestore-types';

export interface User {
  createdAt: Timestamp;
}

This is working good for me in production builds.