TypeScriptでwindowにプロパティを追加する

TypeScriptではwindowに自由にプロパティを追加することはできない

TypeScriptでは、以下のようなコードはエラーになります。

window.foo = 'bar';  

TS2339: Property 'foo' does not exist on type 'Window'.

当然ながら、グローバルのWindowfooなんてプロパティは無いため、代入ができずエラーになります。
そもそも、グローバルオブジェクトであるWindowに干渉することが自体が進められる行為ではありません。

しかし、ブラウザでTypeScriptを使おうと思うと、なかなかそうも言っていられません。
私は以下のシチュエーションで必要になりました。

  • ElectronでRendererプロセスとpreloadのやりとり
  • ChromeExtensionのcontentsスクリプトからページに干渉する

解決方法を2種類

A. interfaceとdeclareを使う

以下のようなWindowを継承したインターフェイスを作成しておきexportします。

// window.ts  
interface MyWindow extends Window {  
    foo: string  
}  
declare var window: MyWindow;  
export default window;  

windowを直接使いたい場面で、この新しく作ったwindowをimportすることで、
自ら定義したwindow以下のプロパティも使用できるようになります。

import window from './window';  

window.foo = 'bar';  

B. declare globalを使う

declara globalを使用すると、
globalの名前空間にある定義を上書きすることができます。

参考: TypeScript の型定義ファイルと仲良くなろう - Hatena Developer Blog

declare global {  
    interface Window {  
        foo: string,  
    }  
}  

window.foo = 'bar';  

export default class baz {  
  //...  
}  

ただ、手元の環境では、同一ファイル内にexportが無い場合は以下のエラーが発生して使えないため、
exportを行わないエントリーポイントのTSでは使用できないので注意しましょう。

Error:(1, 9) TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.

注意点

筆者はTypeScript初心者なので、もしこれらの方法に問題があったり他にいい方法が合った場合はぜひコメントをお願いします。