Angularfire: arrayUnion() throws "FieldValue is missing..." error

Created on 14 Feb 2019  路  5Comments  路  Source: angular/angularfire

Version info

Angular: 7.2.0

Firebase: 5.8.2

AngularFire: 5.1.1


I am trying to update an array "likedPosts" for a User-Document:

User Model:

export interface User {
  uid: string;
  email: string;
  photoURL?: string;
  displayName?: string;
  likedPosts?: string[];
  createdPosts?: string[];
}

Update array:

const userRef: AngularFirestoreDocument<User> = this.afs.doc(
      `users/${uid}`
);
userRef.update({
      likedPosts: firestore.FieldValue.arrayUnion("post23")
});

I am getting the following error:

[ts] Type 'FieldValue' is missing the following properties from type 'string[]': length, pop, push, concat, and 26 more. [2740]
User.ts(6, 3): The expected type comes from property 'likedPosts' which is declared here on type 'Partial'

This is the example code from firebase.com:

var washingtonRef = db.collection("cities").doc("DC");

// Atomically add a new region to the "regions" array field.
washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});

// Atomically remove a region from the "regions" array field.
washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayRemove("east_coast")
});
test.firestore.js

Thank you for your help!

Most helpful comment

I solved this issue by importing firestore from firebase/app
import * as firebase from 'firebase/app';

then using it in update method

this.AngularFirestoreObj.doc('document-path') .ref.update({ arrayField: firebase.firestore.FieldValue.arrayUnion(new_Item)})

All 5 comments

Typescript expects string[] and you provide a different type (arrayUnion does not return a string array)
I suggest to create a new interface called UserUpdate with FieldValue as the type, or add the FieldValue as a second type to regions: string[] | firebase.firestore.FieldValue

I solved this issue by importing firestore from firebase/app
import * as firebase from 'firebase/app';

then using it in update method

this.AngularFirestoreObj.doc('document-path') .ref.update({ arrayField: firebase.firestore.FieldValue.arrayUnion(new_Item)})

Is there a proper/ community agreed upon way of doing this?

The suggestion of creating a new interface called with FieldValue does "work", however it feels like a hack and counter intuitive. Using this approach means you will have to set the AngularFirestoreCollection.doc method to one type when you are updating a document and another type when you are retrieving data from that same document.

@whoiscarlo I agree with you. Acctually if I follow this aproach I'll need to verify my variable with a typeof() a bunch of other places (every where I'm using a regions.length) to avoid another typing errors. Anyone has another solution to this situation?

Alright so this a complete HACK and I'm not necessarily recommending it, but since there's been no word from the contributors I might as well throw it out there for those like me who obsess over these kinds of things. Once again this is definitely a hack and can/will lead to confusion if you aren't extremely clear with how you orignize your data.

Using the original example from the author, I was able to "trick" the compiler by converting the _firebase.firestore.FieldValue_ element into an _unknown_ type then converting that type into the desired type, which in this case is _string[]_

firebase.firestore.FieldValue.arrayUnion('post23') as _unknown_ as _string[]_

Version 1
const userRef: AngularFirestoreDocument<User> = this.afs.doc( 'users/${uid}' );
const addPost = firebase.firestore.FieldValue.arrayUnion('post23') as unknown as string[];
userRef.update({ likedPosts: addPost });

Version 2
const userRef: AngularFirestoreDocument<User> = this.afs.doc( 'users/${uid}' );
userRef.update({ likedPosts: firebase.firestore.FieldValue.arrayUnion('post23') as unknown as string[]; });

Was this page helpful?
0 / 5 - 0 ratings