What is the proper type for a request handler of a firebase HttpsFunction?

Viewed 796

I need to split my functions into multiple files.

This is my index.ts

export const helloWorld = functions.https.onRequest((request, response) => {
  functions.logger.info("Hello logs!", {structuredData: true});
  response.send("Hello from Firebase!");
});

I need it to be something like:

import helloWorldHandler from "./handlers/helloWorldHandler"

export const helloWorld = functions.https.onRequest(helloWorldHandler);

So what should I type the helloWorldHandler request handler?

const helloWorldHandler : ??? = async (req,res) => {
  const result = await someApi();
  functions.logger.info("Hello logs!", {structuredData: true});
  res.send("Hello from Firebase!");
};

export default helloWorldHandler;

I tried:

import * as functions from "firebase-functions";

const helloWorldHandler : functions.HttpsFunction = async (req,res) => { ... };

But I'm getting this error:

Type '(req: Request, res: Response) => Promise<Response>' is not assignable to type 'HttpsFunction'.

Property '__trigger' is missing in type '(req: Request, res: Response) => Promise<Response>' but required in type 'TriggerAnnotated'.

The onRequest() method, the one that should take the handler as a parameter, does not seem to give it a proper type name, rather than a function signature. Do I need to create an alias for that?

enter image description here

4 Answers

The type functions.HttpsFunction is the return type of functions.https.onRequest(), and not the argument to it. A function of this type is exported by your code and defines what needs to be deployed by the Firebase CLI (the region, memory size and so on are stored in the __trigger property).

As you want the type of the first argument to functions.https.onRequest(), you are instead looking for the type:

type HttpsOnRequestHandler = (req: functions.https.Request, resp: functions.Response<any>) => void | Promise<void>

But rather than hard-code this, you can extract it from the Firebase Functions library using either:

import * as functions from "firebase-functions";

type HttpsOnRequestHandler = Parameters<typeof functions.https.onRequest>[0];

or

import { https } from "firebase-functions";

type HttpsOnRequestHandler = Parameters<typeof https.onRequest>[0]

Note: If your code doesn't use the firebase-functions library itself, you can tell TypeScript that you only want its types using import type * as functions from "firebase-functions"; and import type { https } from "firebase-functions"; as appropriate; this removes the import from the compiled JavaScript as its not needed for running the code.

Here is what I've come up with. Still interested in knowing if is there an out-of-the-box type alias for this.

index.ts

import * as functions from "firebase-functions";
import helloWorldHandler from "./handlers/helloWorldHandler"

type Req = functions.https.Request
type Res = functions.Response

// WILL USE THIS EXPORTED TYPE
export type RequestHandler = (req: Req, res: Res) => void | Promise<void>

export const helloWorld = functions.https.onRequest(helloWorldHandler);

helloWorldHandler .ts

import { RequestHandler } from "../index";

const helloWorldHandler : RequestHandler = async (req,res) => { ... };

I'd suggest simply using the provided HttpsFunction type:

import * as functions from "firebase-functions";
import type { HttpsFunction } from "firebase-functions";

export const foo: HttpsFunction = functions.https.onRequest((req, res) => {
    // the types of req and res are known here...
    res.send("HELO");
});

I managed to run the new Firebase Functions v2 in TypeScript with

// import from a specific subpackage
import {onRequest} from "firebase-functions/v2/https";

export default onRequest((request, response) => {
  response.send("Hello from Firebase!");
});
Related