Ad

DocumentReference.set() Called With Invalid Data. Unsupported Field Value: Undefined (found In Field Uid)

So I'm trying to make a signup form for an app, and everything seems to be working just fine except the fact that it throws an error. The data seems to appear in my database, but when i try "ng serve" the compiler give an error.

my browser console spits out the following statement:

DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field uid)

This is the same thing as the title said.

"ERROR in src/app/core/auth.service.ts(57,11): error TS2740: Type '{ uid: any; email: any;
displayName: any; photoURL: any; }' is missing the following properties from type 'User': delete, emailVerified, getIdTokenResult, getIdToken, and 24 more."

I've tried looking for syntax errors, since I'm following a tutorial. Tried checking if there's no upper lower case etc.

The following is my auth.service.ts file

import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { AngularFireAuth } from "angularfire2/auth";
import {
  AngularFirestore,
  AngularFirestoreDocument
} from "angularfire2/firestore";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/switchMap";
import { User } from "firebase";
import { of } from "rxjs";

 interface user {
   uid: string;
   email: string;
   photoURL ? : string;
   displayName ? : string;
 }

 @Injectable()
 export class AuthService {
   user: Observable < user >

     constructor(
       private afAuth: AngularFireAuth,
       private afs: AngularFirestore,
       private router: Router
     ) {
       this.user = this.afAuth.authState.switchMap(user => {
         if (user) {
           return this.afs.doc < User > ('users/${user.uid}').valueChanges();
         } else {
           return of(null)
         }
       })
     }

   emailSignIn(email: string, password: string) {
     return this.afAuth.auth.signInWithEmailAndPassword(email, password)
       .then(() => console.log("You have successfully signed in"))
       .catch(error => console.log(error.message))
   }

   emailSignUp(email: string, password: string) {
     return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
       .then(user => this.updateUserData(user))
       .then(() => console.log("Welcome, your account has been created!"))
       .catch(error => console.log(error.message))
   }

   signOut() {
     return this.afAuth.auth.signOut()
       .then(() => {
         this.router.navigate(['/'])
       })
   }

   private updateUserData(user) {
     const userRef: AngularFirestoreDocument < User > =
       this.afs.doc(`users/${user.uid}`)
     const data: User = {
       uid: user.uid,
       email: user.email || null,
       displayName: user.displayName,
       photoURL: user.photoURL
     }
     return userRef.set(data, {
       merge: true
     })
   }
 }

I just need to get rid of the error, so it wont throw me off in the future. In case something happens to the database in the future, and also for me to learn how to solve these kind of problems.

After in input a new user-email and a valid password, firebase registers the changes and stores it in its database, but for some reason im getting this nasty error, and i dont like seeing red underlined code.

Pretty much just making features for the signup page of the app im creating.

Thank you for any incoming help.

Ad

Answer

Your const data is not of type User interface provided by firebase. You can inspect the firebase User interface in the source code, and it includes properties like the error suggest, or read from official documentation.

you want to to use your interface you have created, i.e user:

const data: user = {
  uid: user.uid,
  email: user.email || null,
  displayName: user.displayName,
  photoURL: user.photoURL
}

That would mean that the doc you want is also of type user:

const userRef: AngularFirestoreDocument<user> = this.afs.doc(`users/${user.uid}`);

Also what you need to return from the signup, is user.user:

return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
  .then(user => this.updateUserData(user.user))

since createUserWithEmailAndPassword returns promise of UserCredential

I see that you are using User as type in other places, so if you encounter other places with similar issues, it would be caused by the same.

As an addition I can mention, what user would the firebase.User be? Well, that is the user you get returned from:

this.afAuth.auth.currentUser
Ad
source: stackoverflow.com
Ad