Cloud Functionsのhttps.onCallはDate型を受け取ってくれない
「いやそんなん常識でしょ」「ちゃんとドキュメント読め」という声も聞こえてきますが、おれは読んでいなかったんだ……! なんか雰囲気で適当に使っていたからハマってしまったんだ……! 初心者なんだ……! 初心者って言い訳すると斧飛んできそうですよね。めっちゃ怖い。許してください。
というわけでタイトルの通りの話をします。ドキュメントへのURLを貼ったらそこでもう終わってしまう話なんですが、せっかくなので具体的なコードとか含めて話します。
きっかけ
ある時、私の中に「Cloud Firestoreに日付登録する前にCloud Functionsでバリデーションかけたいなぁ~」という欲求が発生しました。なので、以下のようなコードを書きました。実際のコードとは違いますが、とりあえずdate型を送ったという雰囲気だけ伝われば。
this.functions.httpsCallable('nankaMethod')({
date: new Date()
})
そして、Cloud Functions側ではそのdateを受け取って、以下のように時間を抽出していました。TypeScriptなのでもしかしたらJavaScriptとちょっとだけ書き方違うかもしれません。引数はanyです。TypeScriptのメリットを殺していますね。
export const nankaMethod = functions.region('asia-northeast1').https.onCall(async (data: any, context: any) => {
const hour: string = data.date.getHours();
}
が、エラーが発生しました。何かわかりませんが「INVALID」とだけ返却されてきます。謎に思いつつログビューアを見ると、以下のようなエラーが発生していました(余談ですが、この頃の私(数日前)はエラーが出たらログビューアを見るという知識すらありませんでした。ハイパー初心者ですね)。
Cannot read property 'getHours' of undefined
どういうことか? タイトルの通りです。クライアンドサイドからDate型で送ったと思っても、Cloud Functionsに着く頃には消滅してしまっているんです。
そんなんありかよ! と思いながら私はドキュメントを検索しました。そして、見つけました。
次の型を使用できます。
・null - null
・int(符号付きまたは符号なし、最大 32 ビット)- 例: 3 または -30。
・float - 例: 3.14
・double - 例: 3.14
・boolean - true または false
・string - 例: "hello world"
・map - 例: {"x": 3}
・list - 例: [1, 2, 3]
・long(符号付きまたは符号なし、最大 64 ビット)
Date型載ってない……。
ならどうするか
まず、CloudFunctionsに渡す際に、対象のDateに対してtoString()を行います。
this.functions.httpsCallable('nankaMethod')({
date: new Date().toString()
})
そして、受け取った側では、文字列をそのままDateで包みます。
export const nankaMethod = functions.region('asia-northeast1').https.onCall(async (data: any, context: any) => {
const hour: string = new Date(data.date).getHours();
}
完成です。力技な気もしますが、できるのでこれでOKだと思います(適当)。
まとめ
string型にして送って、Cloud Functions側でDate型に戻せば良い。
書いててクソ初心者野郎だなと悲しくなってきました。でもほら……とりあえず駄作でもアウトプットしたほうが成長できるって言うじゃないですか……ね……。