珍しくOSS活動をしたので簡単に報告記事を書く。
問題
最近ブラウザ拡張をよく触っている。同僚がmanifest.jsonをTypeScriptから生成できる良い仕組みを整えてくれており、自分も元気に開発を進めたのだが、どうにも型が合わない。最初は型がついたおかげでミスが静的に検出されていいな〜と眺めていたのだけど、よくよく調べるとどうも型定義が間違っている。具体的にはmanifest.d.ts
の以下の箇所。
commands?: WebExtensionManifestCommandsType;
interface WebExtensionManifestCommandsType { /** * Optional. */ suggested_key?: WebExtensionManifestCommandsSuggestedKeyType; /** * Optional. */ description?: string; }
MDNのドキュメントにあるように、commandsは任意のkeyでcommand名を指定しつつ、ショートカットキーの設定を与えることになっている。しかし型定義のほうは、commandsに直接ショートカットキーの設定を与える形になっていて誤っている。commandsはRecord<string, WebExtensionManifestCommandsType>
といった型になっていると良さそうに見える。
解決
型定義を1行直したら解決と思いきやそうではない。MozillaはWebExtensions APIをJSON SchemaライクなAPI Schemaで定義している。今回使っているwebextension-polyfill-tsは、そのAPI Schemaから型定義を自動生成している。今回の問題はその自動生成プロセスのバグによるものであった。
具体的には、API Schemaに対する前処理として、別ファイルでextendしているものをひとつにまとめ(上の例ではmanifest.d.ts
の単位でまとめている)、その上で入れ子になっている定義を分割する(上の例だとWebExtensionManifestCommandsType
のような分割)のだが、その過程でobjectが入れ子構造になっている情報が潰れてしまっていた。
再帰処理の感じから一般のケースとして直すのが難しそうに見えたので、コーナーケースとしてobjectの入れ子を補う処理を加えて修正とした。半信半疑で修正を加えて型定義を再生成したところ、見事に問題の箇所だけdiffができて直ったので自己肯定感がだいぶ高まった。