Guide on building a custom TypeScript converter for Firestore using withConverter() function

I have been exploring the capabilities of the Firebase JavaScript Version 9 SDK.

One feature that caught my attention is the withConverter(), which allows for seamless data casting between Firestore and TypeScript interfaces.

An informative article can be found here, detailing how to use a generic converter to streamline the process. The author demonstrates creating a single generic converter for reusability, eliminating the need for separate converter logic for each interface. For those interested, a GIST with code snippets and detailed explanations is available.

In attempting to implement a similar generic converter, specifically tailored towards a User interface, I encountered a roadblock:

interface User {
  id?: string;
  name: string;
}

const converter = <T>() => ({
  toFirestore: (data: Partial<T>) => data,
  fromFirestore: (snap: FirebaseFirestore.QueryDocumentSnapshot) =>
    snap.data() as T,
});

const userDocRef = doc(db, 'users', 'my-user-id').withConverter(
  converter<User>() // <-- Error here
);

The TypeScript error message displayed upon invoking converter<User>() reads as follows:

No overload matches this call.
  Overload 1 of 2, '(converter: null): DocumentReference<DocumentData>', gave the following error.
  Overload 2 of 2, '(converter: FirestoreDataConverter<User>): DocumentReference<User>', gave the following error. ts(2769)

If anyone has insights into why this error occurs, your input would be greatly appreciated.

Answer №1

Finally cracked the code.

After referring to this informative document, I stumbled upon the appropriate converter types for Version 9 SDK, which turned out to be PartialWithFieldValue and QueryDocumentSnapshot.

Presenting the revised and accurate code below:

interface User {
  id?: string;
  name: string;
}

const customConverter = <T>() => ({
  toFirestore: (data: PartialWithFieldValue<T>) => data,
  fromFirestore: (snap: QueryDocumentSnapshot) => snap.data() as T,
});

const newUserDocRef = doc(db, 'users', 'my-user-id').withConverter(
  customConverter<User>()
);

As a result, newUserDocRef is now equipped with the type of DocumentReference<User>.

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

Dynamically assign values to object properties of varying data types using indexing

My goal is to dynamically update one object using another object of the same type. This object contains properties of different types: type TypeOne = 'good' | 'okay'; type TypeTwo = 'default' | 'one'; interface Opt ...

Having difficulty troubleshooting the /app router application on version 13.4.x

Having trouble debugging a server-side process in my Next.js app that uses the /app router. To reproduce the issue, simply create a new Next.js app with npx create-next-app and select the app router option. I've attempted to attach a debugger to the ...

Issue: Unable to find 'fs' in JS universal application

I am currently developing a Typescript package that needs to be compatible with both front end and back end environments. To determine the environment (browser or node), I am utilizing the following npm package: https://www.npmjs.com/package/browser-or-nod ...

Autoformatting files with ESLint on save

I'm encountering an issue where Visual Studio Code is saving my file in violation of the rules specified in my eslint configuration when using eslint and prettier for formatting. module.exports = { env: { browser: true, es2022: true, nod ...

The concept of type literals in Typescript provides a powerful tool for achieving function

In TypeScript, I am aiming to create an overloaded function with named parameters. Despite the code running correctly, I encounter warnings about `init.index` potentially not existing in one of the function signatures. The purpose of overloading is to off ...

Different Ways to Remove an Element from an Array in TypeScript

I have been browsing through the responses here, but none of them seem to work for me. I am trying to remove an item from an array, but no matter what I do, the index keeps returning as -1. deleteItinerary(id: string) { this.dataSvc.removeItinerar ...

Mat Progress Bar for Tracking Fetch API Requests and Generating XLS Files

I am interested in implementing a mat progress bar to track the progress made while fetching data from the database and creating an XLSX file. The progress does not need to be exact, rough estimates and sudden changes are acceptable. Is it feasible to achi ...

Jest unit tests in Angular using Typescript are not detecting failures when it comes to console errors or unrecognized elements

In my Angular Typescript project, I am facing an issue with my Jest unit test. The test does not fail even if a component (e.g., mat-paginator without importing MatPaginatorModule in configureTestingModule) or template bindings (e.g., [mask] directive from ...

Encountering an issue when trying to download a PDF from an Angular 6 frontend using a Spring Boot API - receiving an error related to

When I directly call the Spring Boot API in the browser, it successfully creates and downloads a PDF report. However, when I try to make the same GET request from Angular 6, I encounter the following error: Here is the code snippet for the Spring Boot (Ja ...

What could be causing the "serviceName error: No provider found" message to appear?

Currently, I am working on sharing a value between two components in Angular. The setup involves a ProjectView component that renders a ProjectViewBudget component as a "child" (created within a dynamic tab component using ComponentFactoryResolver) with th ...

React type-script does not trigger the onClick event for CheckBox

I have created a custom component called MyCheckBox (which I am using as a helper component). I imported this component into another one, but for some reason, the event is not being triggered when I try to click on it. Here is the code for reference: MyC ...

Every time I click on a single button, all the text inputs get updated simultaneously

One issue I encountered is with a component featuring increment and decrement buttons. These buttons are meant to interact with specific products, yet when clicked, all text inputs update simultaneously instead of just the intended one. COMPONENT HTML: &l ...

Populate List Items until Maximum Capacity is Reached and Increase the

Is there a way to make a ListItem fill the list vertically while also being able to overflow it if needed? I'm looking for a solution that would allow me to access the height of the empty space in the list, which I believe would be the minHeight. Som ...

The guidelines specified in the root `.eslintrc.json` file of an NX workspace do not carry over to the project-level `.eslintrc.json` file

In my main .eslintrc.json file, I have set up some rules. This file contains: { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nrwl/nx", "react", "@typescript-eslint", &qu ...

The mock function will only be triggered if it is placed at the beginning of the file

In an attempt to simulate a React function component for the purpose of validating the properties passed to it, I encountered an interesting difference in behavior. When the mock is placed at the top of the file, everything works as expected: const mockTra ...

The ngAfterViewChecked function seems to be caught in an endless loop

I am facing an issue where the <cdk-virtual-scroll-viewport> starts from the bottom, but I am unable to scroll up. I suspect that this problem is related to the use of AfterViewChecked. Even after trying AfterViewInit, the issue persists. @ViewChil ...

Issue with RxDB: Collection not found upon reload

Exploring the integration of RxDB in my Angular project. I wanted to start with a simple example: export const LANG = { version: 0, title: "Language Key", type: "object", properties: { key: { type: "string", primary: true } }, requ ...

What is the best way to iterate through all class properties that are specified using class-validator?

I have a class defined using the class-validator package. class Shape { @IsString() value?: string @IsString() id?: string } I am trying to find a way to retrieve the properties and types specified in this class. Is there a method to do s ...

When selecting a MenuItem, only a ReactOwner has the ability to add a ref using addComponentAsRefTo(...)

I'm currently working on a basic component that looks like this: class App extends React.Component<{}, {}> { constructor() { super(); } render() { return ( <MuiThemeProvider muiTheme={muiTheme}> <div> ...

The Date Filter is causing a glitch in formatting the date value

I have a variable called dateSubmitted with the value of "dateSubmitted": "07-09-20:11:03:30" Currently, I am utilizing Angular Version 7 Within my HTML code, I am using the date filter to format the date like so: <td> {{element.dateSubmi ...