Qiita Advent Calendar 2021
タイムリープTypeScript 〜TypeScript始めたてのあの頃に知っておきたかったこと〜
4日目の記事として
あの頃に知っていれば、こんなに遠回りしなかったgtag設定のエピソードをご紹介します。
さいしょに
window.gtag('config', 測定ID);
TypeScriptのプロジェクトで、このようにGoogle Analyticsの測定のみ記述すると
window.gtag
の型が定義されていないことを指摘するエラーになります。
このエラーから正解にたどり着くまでを、当時をふりかえってまとめてみました。
解決方法
gtagの型定義が公開されているので、インストールすればよい。
@types/gtag.jsをインストールすると、window.gtag
が型定義済みの状態になります。
# npmのプロジェクトへインストールする場合
npm install @types/gtag.js
# yarnのプロジェクトへインストールする場合
yarn add -D @types/gtag.js
初心者のあゆみ
こじらせポイントと、全体のながれをふりかえり
初心者がさまよった様子をみていきます。
こじらせポイント
2つの要素がこじらせて、解決まで時間がかかりました。
Type Searchの存在に気づいていなくて、型定義ファイルを見つけるコツがわかっていなかった
tsconfig.json
の理解が浅いままtypes
を設定していたため
@types/gtag.jsをインストールしただけでグローバルに使用できなかった。
tsconfig.json
には、gtag.js
とは別のパッケージを導入するタイミングで設定したtypes
がありました。
{
"compilerOptions": {
"types": ["hoge"]
},
}
当時をふりかえる
おこった出来事、やったことを、順番にふりかえります。
- 型定義がないのでエラー
-
window
の子要素へ型を追加できる? - 苦肉のany回避
- 型定義をインストールしたけど反応がない…
型定義がないのでエラー
型定義のエラーを予感しつつ、とりあえずgtag
を使うと
やっぱりエラーでした。
Property 'gtag' does not exist on type 'Window & typeof globalThis'. TS2339
gtagはWindowの型にもTypeScriptのglobalThisの型にも存在しません
そうですよね。
この時点でType Searchへアクセスし型定義を検索したら、もっと解決が早かった。
window
の子要素へ型を追加できる?
とはいえ、自分がつくった変数に型を設定できるのは知っているけれど
window
にぶら下がっていても型って設定できるもの?
エラーの文言でそのまま検索すると、windowの子要素にも型を設定できることがわかりました。
なるほど、declare global
というのを設定すると、window
の子供でも型がつけられた!
declare global {
interface Window {
gtag: any;
}
}
any
がESLintにたしなめられていて気持ち悪いけど、エラーが解けて動くようになりました。
苦肉のany回避
any
のままは気持ち悪いけど、gtag.jsの型定義を手作りする根性もなかったので
もう少し検索してみました。
すると、gtag
のイベンを発火させる関数をクッションにするやり方を知りました。
htmlへgtagを設定するついでに、発火させる自作の関数pageViewEvent
も設定し
declare
ではpageViewEvent
の型を設定してany
回避しました。
<script async src="https://www.googletagmanager.com/gtag/js?id=測定ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
// gtagページビュー送信イベントを実行
function pageViewEvent(){
window.gtag('config', 測定ID);
}
</script>
declare global {
interface Window {
pageViewEvent: () => void;
}
}
window.pageViewEvent();
しかし、エラーもないしany
も使わない形にできたけど
ほんとうの意味で型を定義したわけではないのでは?
型定義をインストールしたけど反応がない…
実はこの時点で、
公開されているgtagの型定義があり、それ導入している解説記事を見つけていました。
しかし、手順にしたがってnpm install
しても
window.gtag
が型定義されている状態とならず、行き詰まっていました。
(ここで、しばらく諦めの期間に突入…)
pegeViewEvent
で騙し騙し動かしつつ、手がかりを検索していると
@types/gtag.jsが効いていなかった原因がみつかりました!
ただし、
tsconfig.json
でtypes
が既に設定されている場合はグローバルに検出されません。
types
を取り除くか、gtag.js
をtypes
に追加しましょう。
(Will Squireさんのアドバイス意訳)
tsconfig.json
が影響してたんか…
こじらせポイントにあったよう、gtagを設定しようとしていたプロジェクトでは
types
にhogeが設定されている状態でした。
typesを設定したとき、意味や影響を深堀りせずお手本どおりにしていた。
{
"compilerOptions": {
"types": ["hoge", "gtag.js"]
},
}
こうして、導入の解説記事ではインストールするだけで型定義できていたのに
自分のプロジェクトでは型定義できなかった原因がわかり、全てが解決しました。
さいごに
この記事を書くために、当時あがいたキーワードで思い出し検索したのですが
あのときよりも多くの記事がみつかり
TypeScriptの盛り上がり、というか、もう定着してきている情勢を感じました。
まだまだ習熟度が浅いので、今後ともがんばって勉強します。