Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a method on a cast Typescript class

I'm using Cloud Firestore to cast to an object which is working fine. However it seems I'm unable to call methods on that object. Here's my model definition -

contact.ts

export class Contact {
  id: string
  firstname: string
  lastname: string
  email: string

  getFullname() {
    return this.firstname + this.lastname
  }
}

contact.service.ts

@Injectable()
export class ContactService {
  getAll(raiseId: string): Observable<Contact[]> {
    this.contactsCollection = this.afs.collection<IContact>('contacts')
    this.contacts$ = this.contactsCollection.snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const contact = a.payload.doc.data() as Contact;
        const id = a.payload.doc.id;
        return { id, ...contact };
      }))
    );
    return this.contacts$;
  }
}

contact.component.ts

@Component({
  selector: 'contact-view',
  templateUrl: './contact-view.component.html',
  styleUrls: ['./contact-view.component.scss']
})
export class ContactViewComponent implements OnInit {
  contacts$: Observable<Contact[]>;
  contacts: Contact[];

  constructor(
    public contactService: ContactService
  ) { }

  ngOnInit() {
      this.contacts$ = this.contactService.getAll();
      this.contacts$.subscribe(contacts => {
        this.contacts = contacts;
      })
    })
  }
}

component.component.html

<div *ngFor="let contact in contacts">{{contact.getFullname()}}</div>

But the getFullname() method just throws an error

TypeError: _v.context.$implicit.getFullname is not a function

Could someone explain why this is an if there is a way to call a function on a cast object?

like image 572
Chris Edgington Avatar asked Jun 27 '26 04:06

Chris Edgington


1 Answers

You can't simply cast the object returned by Firestore to any object and assume that it will just work. The object you get from calling data() is just a plain old JavaScript object with properties that match the fields of the document. That's all. It doesn't have any methods, and casting that object to something else doesn't create any methods for you. Casting just changes TypeScript's notion of what that object is, and in this case, you've just fooled TypeScript into thinking you have an instance of Contact, when you really don't.

If you want to turn that Firestore data object into a Contact object, you're going to have to copy the properties of the data object into a new Contact object. An easy way to do that is using Object.assign().

like image 51
Doug Stevenson Avatar answered Jul 02 '26 04:07

Doug Stevenson