2
2

More than 5 years have passed since last update.

TypeScriptで型をDIしてFirestore周りの型チェックをnode/browser向け環境にそれぞれ解決する

Last updated at Posted at 2019-08-30

*こちらの資料 で解決できなかったと記載したfirebase周りの型解決についての記事になります
こちらの資料を元にした記述があるので、目を通してもらえると理解しやすいかと思います

なにがやりたいか

これ

firebaseのFirestoreへのアクセスする処理をfirebase functionsとフロントで使いまわしたい

何が問題か

これ

firestoreの型定義がブラウザ向けとfunctions向けで別物になっていて、ブラウザ向けは lib.dom.d.tsへ依存しているなど、トランスパイル時に両方を満たすうまい方法が見つけられなかった

firebaseのjs向けsdkは、ブラウザ環境で利用するための firebaseパッケージと、node環境で利用するための firebase-adminパッケージがあります。
これらは共に Firestoreクラスの定義を(何故か)それぞれ持っています
またそれらは、例えばServiceWorkerのような環境に依存する値に依存しています

つまり、いわゆるRepository層を作ってそれをfirebase functionsとフロント双方で使おうとするとTypeScriptのトランスパイル時に型検査エラーとなります

今回はこれを解決しました

どうやったか

解決したcommit
https://github.com/sisisin-sandbox/monorepo-tsconfig/commit/ec424adc9dfff71f4450c4ce92c30d75f1c3f67f

(このリポジトリ構成についてはこの辺参考のこと)


  • それぞれの環境向けのtsconfigを用意
  • また、それぞれの環境向けのfirebase.d.tsを用意
node向けfirebase.d.ts
// 別名にしておかないとfirebase変数を参照したときに `firebase` パッケージのものを参照してしまう
import { firestore as adminFirestore } from 'firebase-admin';

declare module 'firebase' {
  export interface MyFirestore extends adminFirestore.Firestore {}
}
ブラウザ向けfirebase.d.ts
import { firestore } from 'firebase';

declare module 'firebase' {
  export interface MyFirestore extends firestore.Firestore {}
}
  • Repositoryは上記で作成した MyFirestore型を使って型付けする
HogeRepository.ts
import { MyFirestore } from 'firebase';

export class HogeRepository {
  constructor(private db: MyFirestore) {}
// 以下略
  • それぞれの環境向けのtsconfigで、 includeに上記型定義ファイルを含めるようにする

概ね以上になります

つまりどういうこと?

何が問題だったかと言うと、型がnode/browser環境下でそれぞれ違うということなので、それぞれの環境用にトランスパイル出来るようにしつつ、型をトランスパイル時に差し替えということをやりました
つまりトランスパイル時に型についてDependency Injectionしたことになりますね!

この構成だと、front,sharedという2つのパッケージをブラウザ向けにトランスパイルしたいので front/tsconfig.json 及び shared/tsconfig.browser.jsoninclude にブラウザ向けfirebase.d.tsを含めるようにして解決。
functionsも同様、といった具合です

そもそもfirebaseの型定義がuniversalを意識して書かれていればこんなことにはならないんですが、まあしょうがないということで。
あまり起こる事象ではないでしょうが、複数環境向けのリポジトリで同様の課題にあたったときに同じアプローチで解決出来ると思います


次回は資料のもう一つの心残り、 functionsから shared/lib/esのimportがあったとき(またはその逆)にトランスパイルエラーにならない をpaths使って解決する編になる気がします(やる気があれば)

2
2
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
2
2