5
6

More than 3 years have passed since last update.

CloudFunctionsのhttpCallable()をTypeScriptで型安全に使う【Firebase】

Last updated at Posted at 2019-12-17

TL;DR

getSanitizedMessage.ts
import firebase from 'firebase';
import 'firebase/functions';

interface GetSanitizedMessageResponse
  extends firebase.functions.HttpsCallableResult {
  readonly data: {
    ok: boolean;
    text: string;
  };
}

const getSanitizedMessage = async (): Promise<string> => {
  const addMessage: firebase.functions.HttpsCallable = firebase
    .functions()
    .httpsCallable('addMessage');
  const result: GetSanitizedMessageResponse = await addMessage({
    text: 'messageText',
  });
  return result.data.text;
};

事始め

Cloud Functions for Firebaseをクライアントアプリから叩く際、HttpsCallableを重宝するのですが、
TypeScriptで型付けする方法がドキュメントになかったため、その備忘録になります。
冒頭に全コードを載せましたが、単純に型拡張するだけです。

型なしで書く

httpCallable()とはなんぞやという方はこちらを参照してください。

まず、ドキュメントに沿って普通の呼び出しをJSで書くとこんな感じになります。

getSanitizedMessage.js
const getSanitizedMessage = async () => {
  const addMessage = firebase.functions().httpsCallable('addMessage');
  const result = await addMessage({ text: 'messageText' });
  return result.data.text;
};

TSに書き換える

これを型推論せずにTSで書くとこうなります。

getSanitizedMessage.ts
const getSanitizedMessage = async (): Promise<any> => {
  const addMessage: firebase.functions.HttpsCallable = firebase
    .functions()
    .httpsCallable('addMessage');
  const result: firebase.functions.HttpsCallableResult = await addMessage({
    text: 'messageText',
  });
  return result.data.text; // textがany型になる
};

このままだとgetSanitizedMessage()の返り値の型がanyになってしまいます。
result.data.textHttpsCallableResultに定義されていないためです。

このHttpsCallableResult、内実は

firebase/index.d.ts
export interface HttpsCallableResult {
  readonly data: any;
}

のようになっており、要はこれを拡張した型定義を自前で用意すればよいわけです。

型拡張する

CloudFunctionsの実行結果を反映した、レスポンスの型を定義します。

getSanitizedMessage.ts
interface GetSanitizedMessageResponse
  extends firebase.functions.HttpsCallableResult {
  readonly data: {
    ok: boolean;
    text: string;
  };
}

あとはこれを型として使うだけです。

const getSanitizedMessage = async (): Promise<string> => {
  const addMessage: firebase.functions.HttpsCallable = firebase
    .functions()
    .httpsCallable('addMessage');
  const result: GetSanitizedMessageResponse = await addMessage({
    text: 'messageText',
  });
  return result.data.text; // textがstring型になる
};
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6