🎇
firebase v9でupdateが(少し)型安全になりました
先日ついにfirebase v9が リリースされました
知っている限り、v9ではモジュール式(ESM?)になっただけで、バンドルサイズの最適化以外の機能はないのですが、updateに関しては型定義での更新があったので紹介します。
v9の使い方
少しv9の使い方を紹介します。v8までのようにクラスで実装するとtree shakeしづらいので、全て関数になりました。
import { initializeApp } from "firebase/app";
const app = initializeApp({ projectId: "..." });
const DB = getFirestore(app);
const userDoc = doc(DB, "user", "userId");
setDoc(userDoc, { hoge: "fuga" });
updateDoc(userDoc, { piyo: "ponyo" });
deleteDoc(userDoc);
getDoc(userDoc);
わかりやすいですね。
updateで型がつく
本題です。これまじで感動したんですが、updateで型がつきます
type Room = {
size: number;
rooms: {
living: number;
dining: number;
kitchen: number;
};
level1: {
level2: { level3: string };
level2_1: string[];
};
};
const roomDocRef = doc(DB, "rooms", "roomId") as DocumentReference<Room>;
updateDoc(roomDocRef, { "rooms.living": 123 }); // ✅
updateDoc(roomDocRef, { "rooms.living": "abc" }); // ❌ 型 'string' を型 'number | FieldValue' に割り当てることはできません。
updateDoc(roomDocRef, { "level1.level2": { level3: "abc" } }); // ✅
updateDoc(roomDocRef, { "level1.level2": { level3: 123 } }); // ❌: 型 'number' を型 'string | FieldValue' に割り当てることはできません。
updateDoc(roomDocRef, { "level1.level2_1": arrayUnion("asd") }); // ✅
updateDoc(roomDocRef, { "rooms.living": increment(1) }); // ✅
DocumentReference
がちゃんと型付けされていると、ネストしたプロパティまで推論されます。やばいです。圧倒的に型安全。typoで一日デバッグすることが無くなります。
ただし、ちょっと残念なのが、下の例のような場合です。
arrayUnion
やincrement
などの返り値は一律にFieldValue
となっているので、それぞれの区別がつきません。そのうえ、FieldValue
型はどんなプロパティにも渡せます。だから例えば配列にincrement
を渡してもエラーが出ないので注意が必要です。それと、null
やundefined
もFieldValue
扱いになっているようでどのプロパティに渡しても受け入れられます。あまり過信するのは危険ですね。
updateDoc(roomDocRef, { "level1.level2_1": increment(243) }); // ✅ 🤔🤔🤔🤔🤔
updateDoc(roomDocRef, { "level1.level2_1": serverTimestamp() }); //✅ 🤔🤔🤔🤔🤔
updateDoc(roomDocRef, { "level1.level2_1": Timestamp.fromDate(new Date()) }); // ✅ 🤔🤔🤔🤔🤔
updateDoc(roomDocRef, { "level1.level2_1": null }); // ✅ 🤔🤔🤔🤔🤔
updateDoc(roomDocRef, { "level1.level2_1": undefined }); // ✅ 🤔🤔🤔🤔🤔
なお、batch
やrunTransaction
でも同じでした。
変わらないところ
queryももしかしたら進化したかも!?と思ったら変わりませんでした。ジェネリクスでもないのでどうしようもないです。
const roomColRef = collection(
DB,
"rooms",
"roomId"
) as CollectionReference<Room>;
const q = query(
roomColRef,
where("hogehoge", "==", "piyopiyo"), ✅ 🤔🤔🤔🤔🤔
orderBy("fuga") ✅ 🤔🤔🤔🤔🤔
);
Discussion