Writing Cloud Functions with Typescript
Serverless architectures are awesome and I recently started to use Cloud Functions (via Firebase). Immediately, I looked into using Typescript to write my functions. There are mainly two reasons for that: 1) my projects are written in Typescript it would be useful to use some of these files in my functions; 2) out of the box, Cloud Functions provides typings for Typescript, lowering the barrier to entry this new API.
First, created a functions folder within my own project with the following package.json.
{
"name": "myproject-functions",
"version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"firebase-admin": "^4.2.0",
"firebase-functions": "^0.5.4",
"lodash": "^4.17.4"
},
"devDependencies": {
"typescript": "^2.2.2"
}
}
We also need to add a tsconfig.json file into the functions folder. In the package.json of the root project, You can update your lint script to also check the functions folder. In my projects, it looks like this:
tslint --project tsconfig.json && tslint --project functions/tsconfig.json
TypeRoots
By default, Typescript will look into parent node_modules folders to resolve types which can cause quite some confusion when compiling. To avoid this chaos, there is a compiler option called typeRoots that allows you to specify the root type folder. You can set it in your tsconfig.json under the compilerOptions sections as:
"typeRoots":["node_modules/@types"]
Imports
If you use es6 module imports in your functions, you will need to do some modifications to your code. This is because Cloud functions wraps the JS code into a function invocation. Consider the function below.
import functions from "firebase-functions";
import {Request, Response} from "express";
exports.myFunctions = functions.https.onRequest((req, res) => {
//...
})
At deployment, you will get the error below.
You can fix it by using require instead of import. If you only import types, you can still use import since these declarations won’t be present in the generated JS file.
const functions = require("firebase-functions");
// If we only import types, we can use import.
import {Request, Response} from "express";
exports.myFunctions = functions.https.onRequest((req, res) => {
//...
})
Et voilà
I hope this article was helpful to you, and I look forward to receiving your feedback.
Sr. Software Engineer at Enzy
7 年the typeRoots thing was killing me. Thanks for this. I have been looking all over for a solution to the thousands of lines of warnings from typescript.