skip to Main Content

Issue Description:

I am having trouble setting the region property of my Gen 2 Firebase Functions using TypeScript and a parameterized variable due to type mismatch issues. Here’s a sample of my .env file:

LOCATION="australia-southeast1"

I have attempted to define the region both globally and at the function level.

1. Defining region globally using setGlobalOptions

I would prefer to define the region globally using setGlobalOptions.

The global region property on setGlobalOptions has a type of GlobalOptions.region?: string | Expression<string> | ResetValue | undefined. This is slightly different from the function level type HttpsOptions.region?: string | string[] | Expression<string> | ResetValue | undefined as the global level only allows for a singular string and no string[].

No matter what I do at the global level, it fails. All three of these attempts give a deployment error Error: Illegal type coercion of param LOCATION to type string[]:

setGlobalOptions({
  region: defineString("LOCATION"),
});
setGlobalOptions({
  region: defineString("LOCATION") as unknown as string,
});
setGlobalOptions({
  region: defineList("LOCATION") as unknown as string,
});

Therefore, I am unsure how to define region on setGlobalOptions using a parameterized variable.

2. Defining region at the function level

When I tried defining region at the function level, the IDE showed region as HttpsOptions.region?: string | string[] | Expression<string> | ResetValue | undefined.

I thought defineString() would work as it returns a string. Although there were no errors in the IDE, during deployment I received this error Error: Illegal type coercion of param LOCATION to type string[].

import { onCall } from "firebase-functions/v2/https";
import { testValidators } from "../../../services/tests";
import { defineString } from "firebase-functions/params";

export const functionName = onCall(
  {
    region: defineString("LOCATION"),
  },
  (request) => {
    testValidators(request);
  }
);

Next, I tried to define the region using defineList(), but that produced a type error in the IDE:

import { onCall } from "firebase-functions/v2/https";
import { testValidators } from "../../../services/tests";
import { defineString } from "firebase-functions/params";

export const functionName = onCall(
  {
    region: defineList("LOCATION"),
  },
  (request) => {
    testValidators(request);
  }
);

Here is the IDE error:

Type 'ListParam' is not assignable to type 'string | string[] | Expression<string> | ResetValue | undefined'.
  Type 'ListParam' is not assignable to type 'Expression<string>'.
    The types returned by 'value()' are incompatible between these types.
      Type 'string[]' is not assignable to type 'string'.ts(2322)

The following works, but it is confusing because region should accept a string, so why do I need to use defineList() and further assert it with defineList("LOCATION") as unknown as string[]?

import { onCall } from "firebase-functions/v2/https";
import { testValidators } from "../../../services/tests";
import { defineString } from "firebase-functions/params";

export const functionName = onCall(
  {
    region: defineList("LOCATION") as unknown as string[],
  },
  (request) => {
    testValidators(request);
  }
);

Overall there seems to be a lot of problems with the typing for region both at the function and global level.

I managed to get the function level working with an assertion, but I would still prefer to use region on setGlobalOptions with a parameterized variable.

Any help to resolve this issue would be greatly appreciated!

Environment:

  • Node.js: 16.16.0
  • firebase-functions: 4.4.1
  • firebase-tools: 12.4.4
  • firebase-admin: 11.10.1

2

Answers


  1. Chosen as BEST ANSWER

    I reported this as an issue and Google has put out a fix that will be merged soon.


  2. According to this answer provided by Jed Choi you have to set the region using DefineList as unknown then use it as region: <string[]>secret_value,
    Here’s updated code for you :

    import { onCall } from "firebase-functions/v2/https";
    import { testValidators } from "../../../services/tests";
    import { defineString } from "firebase-functions/params";
    
    // you must specify type as unknown explicitly
    const location:unknown = defineList("LOCATION")
    
    export const functionName = onCall(
      {
        region: <string[]>location, // you should cast as sting[]
      },
      (request) => {
        testValidators(request);
      }
    );
    

    If you choose to use firebase functions gen1 then you can follow this answer

    Update:

    I have tested : You can set the region globally with setGlobalOptions with the defineList but you need to specify it as a string so at runtime you will get delimiter , :

    import { setGlobalOptions } from "firebase-functions/v2/options";
    import { defineList } from "firebase-functions/params";
    
    const region = defineList("REGIONS", {
        default: ["australia-southeast1", "asia-east1"]
    });
    
    setGlobalOptions({
      region: region as unknown as string
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search