Transforming TypeScript snapshot data in Firebase Cloud Functions into a string format for notification purposes

I've encountered the following code for cloud functions, which is intended to send a notification to the user upon the creation of a new follower. However, I'm facing an issue regarding converting the snap into a string in order to address the error message provided below.

 function sendNewFollowNotificationFunc(uuid: string, newFollower: string) {
  // const userRef = admin.database().ref('PeopleWhoFollowMe').child(uuid)
  // const fetchAndUpdate = userRef.once('value')
  console.log('User to send notification', uuid);

  admin.database().ref(`UsersFireTokens`).child(uuid).child("token").once('value')
  .then(snap => {
    const token = snap.val//I dont know how, from here I should be handling this inorder to get the value at this location which is the token
    // This registration token comes from the client FCM SDKs.
    var registrationToken = token;

    var message = {
      data: {
        text: 'This is a test',
        time: '2:45'
      },
      token: registrationToken
    };

    // Send a message to the device corresponding to the provided
    // registration token.
    admin.messaging().send(message)//error here
      .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
      })
      .catch((error) => {
        console.log('Error sending message:', error);
      });
  })
  .catch(error => {
    console.log("Error in catch: "+error)
    response.status(500).send(error)
  })

Several errors are occurring, such as:

Argument of type '{ data: { text: string; time: string; }; token: string | null; }' is not assignable to parameter of type 'Message'. Type '{ data: { text: string; time: string; }; token: string | null; }' is not assignable to type 'TokenMessage'. Types of property 'token' are incompatible. Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.ts(2345)

What am I doing wrong and how can I fix it?

Update:

This is my code:

function sendNewFollowNotificationFunc(uuid: string, newFollower: string) {
  // const userRef = admin.database().ref('PeopleWhoFollowMe').child(uuid)
  // const fetchAndUpdate = userRef.once('value')
  console.log('User to send notification', uuid);

  admin.database().ref(`UsersFireTokens`).child(uuid).child("token").once('value')
  .then(snap => {
    //What should I be doing here and how?
console.log('token value', snap.val);//doing this returns a strange function thing in the logs

  })
  .catch(error => {
    console.log("Error in catch: "+error)
    response.status(500).send(error)
  })
}

Answer №1

The complex and lengthy tsc message indicates that the type of your message variable is:

{ data: { text: string; time: string; }; token: string | null; }

however, the send function requires a TokenMessage. It is not possible to fully understand the structure of the TokenMessage from your code alone, but it seems to include a token field of type string. On the other hand, your message has a token field with type string | null. This mismatch in types suggests that your message may lack a token, whereas the send function expects a value with an assured token string.

What am I doing wrong and how can I fix it?

You need to ensure that when calling send, the provided value aligns with the TokenMessage type.

One approach is to cast the message to TokenMessage:

 admin.messaging().send(message as Message)

(tldr: using the above line will likely resolve your issue)

In some cases, two types are too incompatible for casting. In such scenarios, forcing a conversion as shown above may not work. Instead, you could first cast to any and then to the desired type:

admin.messaging().send(message as any as Message)


That being said, this may not always be the recommended course of action:

If TypeScript raises concerns about message potentially lacking a token, it's useful. Typically, you can address these tsc warnings by asserting over your variables:

function getToken(): string | null {
    return 'f00';
}

function test(s: string) { 

}

const t = getToken();

test(t); // error

if (t) {
    test(t); // no error, considered safe
    // this practice ensures handling of potential null values during development
}

However, this method doesn't seem applicable to object fields:

function getToken(): string | null {
    return 'f00';
}

interface Message{
    token: string;
}

function send(m: Message) { 

}

const t = getToken();

const message = {
    token: t,
}

send(message); // error

if (t) {
    send(message); // error
}

if (message.token) { 
    send(message); // still an error, which is perplexing. At this point, tsc should recognize that message meets the requirements of Message. There appears to be a confusion here.
}

send(message as Message); // valid

In general, it is advisable and safer to handle null checks through if statements rather than manual type casting. However, there can be instances where alternative options are limited.

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

How can I effectively implement a withAuth higher order component (HOC) in TypeScript within Next.js?

Currently, I am working on a Next.js application and implementing the next-auth package. My goal is to develop a Higher Order Component (HOC) that can determine if the component has an active session or not. Along with this, I am utilizing eslint for code ...

Angular Obsidian Theme

Hey there! I've successfully implemented a toggle button that switches my Ionic 3 app to dark mode. However, I'm unsure about where exactly I should define the global class [class.dark-theme]="dark". It's essential for this class to be in th ...

You cannot call this expression. The type 'String' does not have any call signatures. Error ts(2349)

Here is the User class I am working with: class User { private _email: string; public get email(): string { return this._email; } public set email(value: string) { this._email = value; } ...

How to build a login page with a static header and footer using Angular2

For my latest project, I am currently in the process of developing an application using Angular2 and eclipse Neon. Utilizing angular-cli for this app, I am now focused on creating the login page. Within the app.component.html file, you will find the follow ...

It appears that TypeScript is generating incorrect 'this' code without giving any warning

I seem to be facing some resistance filing a feature request related to this on GitHub issues, so I'll give it a shot here. Here is the code snippet that caused me trouble: export class Example { readonly myOtherElement: HTMLElement; public ...

`A bug in my Angular 4 application causes a TypeError when hosted on IIS`

After hosting an Angular 4 app on IIS, it seems there is an issue when accessing the app from machines other than the ones used for development. An error message " 'Uncaught TypeError: undefined is not a function' common.es5.js:3084" appears on t ...

What is the reason for the retrieval of jquery-3.5.1.min.js through the request.params.id expression?

For my school project, I am using Express.js with TypeScript to create a simple app. This router is used for the edit page of a contact list we are developing. It displays the ID of the current contact being edited in the search bar. The problem arises whe ...

Angular 2 lacks compatibility with SVG

I have a website where I want to include SVG images inline with my HTML using Angular 2. However, when I try to load the SVG icons within a component, they do not display correctly. Instead, I see the following: https://i.sstatic.net/Ozo6E.png You can vi ...

Troubleshooting the order of Javascript execution in bundled TypeScript applications

I encountered an issue with the execution order of generated JavaScript code during bundling, resulting in an error message when everything is bundled together. An error occurred: [$injector:nomod] Module 'app.demo' is not accessible! This cou ...

Error encountered on login page: The protocol 'http' does not exist (related to HTML, TypeScript, Angular2, and JavaScript)

Screenshot of the issue: Access the complete project here: Link to a Plunker example of a log-in screen: http://plnkr.co/edit/j69yu9cSIQRL2GJZFCd1?p=preview (The username and password for this example are both set as "test") Snippet with the error in ...

Determine the data type of a parameter by referencing a prior parameter

Consider a scenario in my software where I have two distinct implementations of an Event Emitter. For instance: type HandlerA = (data: boolean) => void; type HandlerB = (data: number) => void; // HandlerB is somehow different from HandlerA type Eve ...

Django and Angular combine to create a floral mapping feature that allows users to easily return to their task list

I am looking to arrange the output from the flower library (/api/tasks) into a list of objects. The current response includes multiple objects, but lacks a "list wrapper", making it difficult to iterate over. API: An example of the return is as follows: H ...

Mongoose and TypeScript - the _id being returned seems to be in an unfamiliar format

Experiencing unusual results when querying MongoDB (via Mongoose) from TypeScript. Defined the following two interfaces: import { Document, Types } from "mongoose"; export interface IModule extends Document { _id: Types.ObjectId; name: stri ...

There is an issue with types in React when using TypeScript: The type '(user: User) => Element' cannot be assigned to the type '((props: User) => any) & ReactNode'

I'm encountering an error in the terminal and need some assistance. I am not well-versed in TypeScript, so any guidance to resolve this issue would be highly appreciated. https://i.stack.imgur.com/PWATV.png The Loadable component code: import { Circ ...

The element is implicitly assigned an 'any' type due to the fact that an expression of type 'any' cannot be used to index types in nodejs and solidity

I am in need of setting networks in my contract using NodeJS and TypeScript. Below is the code I have written: let networkId: any = await global.web3.eth.net.getId(); let tetherData = await Tether.networks[networkId]; Unfortunately, I encountered ...

Trigger change event on model update in Angular 4 checkboxes

CSS <div class="checkbox-item"> <input type="checkbox" id="1" [(ngModel)]="filter" (change)="onFilterChange($event)"> CheckBox </div> <button (click)="filter = !filter">Change Status</button> JavaScript export class Filt ...

Managing component composition in React/TypeScript: What's the best way to approach it?

I am brand new to the world of typescript, so please be patient with me. My objective is to transform this react component: interface ButtonProps {...} const Button: React.FC<ButtonProps> = ({ children, href, value as = 'button', ...

Encountering a situation where the data retrieved from Firestore in Angular TypeScript is returning as

I am encountering an issue with retrieving the eventID value from my Events collection in Firestore. Although I am able to successfully display all the events in my app, I require the eventID for additional functionalities. As someone new to TypeScript an ...

A guide on altering the color of a badge through programming

I am curious to learn how I can dynamically change the color of a badge in Angular. My goal is to initially set the color of the badge to white, and then if the percVLRiskTotal reaches a specific value, change the color to green as an example. CSS: <sp ...

Utilizing an observer to encapsulate a custom React hook- a comprehensive guide

As part of my project, I have developed a unique custom react hook that relies on observable state from the store for its dependencies within useEffect: Here is an example of my custom hook: const useFoo = (() => { const { count } = store; useEff ...