Sampath
Sampath

Reputation: 65860

firebase.firestore.FieldValue.serverTimestamp() doesn't support Timestamp data type

 async createUser(uid: string, email: string) {
    await this.afs.doc<UserProfileModel>(FirestoreDbConstant.USER_PROFILES + `/${uid}`).set({
      email,
      createdDate: firebase.firestore.FieldValue.serverTimestamp(),
    });
  }

This model works

export interface UserProfileModel {
    email: string;
    createdDate?: firebase.firestore.FieldValue;
}

But Why I cannot use Timestamp here like so?

import { Timestamp } from '@firebase/firestore-types';

export interface UserProfileModel {
    email: string;
    createdDate?: Timestamp;
}

Then it gives this error:

(property) UserProfileModel.createdDate?: Timestamp Type 'FieldValue' is missing the following properties from type 'Timestamp': seconds, nanoseconds, toDate, toMillists(2739) user-profile.model.ts(11, 5): The expected type comes from property 'createdDate' which is declared here on type 'UserProfileModel'

The problem here is I need to use toDate() on the template. But it doesn't work with the createdDate?: firebase.firestore.FieldValue;

<p>{{invitedEvent.startDatetime.toDate() | amDateFormat: 'MMM DD'}}</p>

Upvotes: 6

Views: 3748

Answers (3)

Will Carle
Will Carle

Reputation: 51

Another option for this is to define your own interface that partially extends both Timestamp and FieldValue

    export interface MyTimestamp extends Partial<FieldValue>, Partial<Timestamp>
    {
      isEqual: (other: any) => boolean;
      valueOf: () => any;
    }

Then you can set your timestamp props to:

    export interface UserProfileModel {
        email: string;
        createdDate?: MyTimestamp;
    }

You'll then get proper types for both writing and reading to firestore

The one caveat is that all props and functions are now optional so if you want to call toDate() on Timestamp for example you'll need to use ? user.createdDate?.toDate?.()

Writing:

user.createdDate = FieldValue.serverTimestamp();

Reading:

user.createdDate?.toDate?.();

Upvotes: 0

This might be better than 'any' or duplicating models :

lastModified: Timestamp | FieldValue;

Upvotes: 5

Doug Stevenson
Doug Stevenson

Reputation: 317322

As you can see from the JavaScript API documentation for serverTimestamp():

serverTimestamp(): FieldValue

Returns a sentinel used with set() or update() to include a server-generated timestamp in the written data.

Returns FieldValue

It doesn't return a Timestamp type. It returns a FieldValue, whose value is actually just a placeholder for a special value that tell the server to generate the timestamp. The client doesn't generate this timestamp at all, since we can't trust the client device's clock.

This means you can't really use the same model for reading and writing records that use server timestamps. On the way in, it will be a FieldValue. On the way out (when you query the document), it will be a Timestamp.

Upvotes: 7

Related Questions