Executing a function on a converted TypeScript object

My experience with using Cloud Firestore has been smooth in casting to an object, but I have encountered an issue when trying to call methods on that object. Below is the model definition I am working with -

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>

Despite following the correct model definition, the getFullname() method is triggering an error

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

It would be helpful if someone could shed light on why this issue is arising and if there is a workaround to call a function on a cast object.

Answer №1

When working with Firestore data, it's important to remember that simply casting the object returned by Firestore to any object won't automatically make it behave as expected. The object obtained from calling data() is just a basic JavaScript object with properties that correspond to the fields of the document. It lacks any methods, so converting it to another type won't add any methods for you. Essentially, casting changes TypeScript's understanding of the object, creating the illusion that you have an instance of Contact when you really don't.

If you intend to transform the Firestore data object into a Contact object, you'll need to manually transfer the properties from the data object to a new Contact object. One convenient method to achieve this is by using Object.assign().

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Rollup ESM creates faulty imports

I need to package a TypeScript React app as a component in an ES module or UMD, but the ES bundle generated is producing an invalid JS module. When bundling, I receive the following hints. However, I am unable to find a solution for this. (!) Missing glob ...

Data binding with ngModel is contingent on certain conditions

I am facing an issue with conditional data binding using ngModel in Angular4. Let me explain further: I have a small form: <form-question-radio [(ngModel)]="model['q4']" name="question" [options]="[{value:true, label:'Yes'}, ...

Encountering a POST 504 error while attempting to proxy an Angular application to a Node server

error message: Failed to connect to http://localhost:4200/api/user/login with a 504 Gateway Timeout error. Encountered this issue while attempting to set up a login feature in my Angular application and establish communication with the Express backend. Th ...

Encountering difficulties with installing TypeScript

I am facing an issue while trying to install TypeScript on Windows 10 using node version 6.3.0 and npm version 3.10.3. The error message I'm getting is as follows: 33 warning Windows_NT 10.0.10586 34 warning argv "C:\\Program Files\&bs ...

Adjust the height of Ngx Editor to meet your specific preferences

I have integrated ngx-editor into my MEAN stack application to create a wysiwyg editor. Everything is functioning as expected, but I am facing an issue with setting the height for the editor. I attempted to define the height in the component's css fil ...

Symfony using Vite with Vue 3 encounters an error: Uncaught ReferenceError - exports is undefined

Currently, I am in the process of developing a Symfony 3 Application with Vite and Vue3 integrated with TypeScript. To replace Symfony's Webpack Encore, I opted for the Vite Buildtool using this convenient plugin: https://github.com/lhapaipai/vite-bu ...

Discovering the data types for node.js imports

When starting a node.js project with express, the code typically begins like this - import express = require('express') const app = express() If I want to pass the variable 'app' as a parameter in typescript, what would be the appropri ...

The library "vue-property-decorator" (v10.X) is causing issues with resolving in Webpack despite being successfully installed

Encountered an error message Module not found: Error: Can't resolve './decorators/Emit' while attempting to import functionality from the library vue-property-decorator. The package is installed and accessible, ruling out a simple installati ...

"Enhance your web development with TypeScript and react-select

I find myself in a peculiar predicament. Currently, I am immersing myself in learning TypeScript and here is a brief overview of what transpired so far: const [selectedBankCode , setSelectedBankCode] = useState<string | undefined>(); const [selecte ...

Using Angular 4 to populate a form and ensure it remains untouched

Designed an update form that is pre-populated with information. I am aiming for the button to be inactive until any changes are made within the form The form group utilizes valueChanges to detect when information has been modified However, even when I u ...

Exploring Angular 7: A guide to implementing seamless pagination with routing for fetching API data

I am new to Angular and I would like some assistance. https://i.sstatic.net/fjpjz.png I need to modify the Route URL http://my_project/products/page/3 when the page changes. The API server provides data through paging, with URLs structured like http://a ...

Using `@HostListener` with `e: TouchEvent` is known to trigger a crash in Firefox, displaying the error message "ReferenceError: TouchEvent is not defined."

When using @HostListener with the event parameter explicitly typed as a TouchEvent, it triggers Firefox to crash and display an error message: ReferenceError: TouchEvent is not defined. This can be illustrated with the following example: @HostListener ...

Tips for setting an argument with a promise data type

I am currently working on writing unit tests using jest to test two functions in a separate file called generator, where I generate fake data : generator.ts export async function generateReportData(overide = {}) { return { clientId: faker.data ...

What is the process for importing Angular Material into a project?

After successfully installing Angular Material Design, I am now attempting to integrate it into my app.module.ts file: import { MaterialModule } from '@angular/material'; What should I specify within the imports: [] section in order to load all ...

Suddenly encountered issue when working with TypeScript Interfaces while integrating Quicktype 'allOf'

Our transition from using JSON Type Definition to JSON Schema includes the utilization of Quicktype to convert JSON Schemas into TypeScript Types. While Quicktype has been effective in most cases, it seems to struggle with converting Discriminators and mor ...

A step-by-step guide on deploying an application using ASP.NET Core and Angular within Visual Studio

I recently completed a tutorial on integrating ASP.NET Core with Angular, which you can find at this link. After following the tutorial, I successfully set up a solution that includes both a backend ASP.NET Core and an angular client application. However ...

Encountering issues following the integration of @angular/flex-layout into an Angular project

After careful consideration, I opted to utilize the responsive grid system provided by @angular/flex-layout instead of Bootstrap. By simply installing the npm package and adding it to my AppModule, I was able to integrate it seamlessly: import { NgModule ...

The attribute 'nameFormControl' is not a valid property on the 'ContactComponent' component

Greetings, StackOverflow community! I'm currently working on an Angular + Node app and I've run into a major problem related to forms and validators in Material Angular. Right now, I'm facing an issue where the HTML component is not recogn ...

Prevent overlapping of range sliders in HTML and CSS

I have designed a range slider with two buttons, but they are overlapping each other. I want to ensure that they do not cross over one another - where the value of the first button should be equal to the minimum value of the second button, and the maximum ...

When changing the dropdown option on a separate page in React/Next JS, all checkboxes show the clicked style as a result of utilizing useState

I have implemented checkboxes for three different categories: "Types", "Price", and "Categories". They function correctly, with data being passed to a separate checkbox component without any issues. The problem arises when I click a checkbox and then inte ...