TypeScript モジュールの拡張とネストされた JavaScript ファイルの処理
TypeScript におけるモジュールの拡張の基本と、ネストされた JavaScript ファイルに型定義を追加する方法を学びます。
TypeScript は、JavaScript コードに型の安全性を提供する能力のおかげで、10 年以上にわたり JavaScript エコシステムに貴重な追加機能をもたらし、その人気を高めてきました。
JavaScript パッケージの型
後方互換性と柔軟性のために、TypeScript はパッケージの作者に対して、彼らの JavaScript パッケージのための型定義を提供することを許可します。そのような型定義は通常、"DefinitelyTyped" リポジトリに保存されています。これらの型定義は @types
スコープを使用してインストールできます。例えば、@types/react
は React パッケージのための型定義です。
これらの型定義をインストールした後は、型の安全性を確信してパッケージを使用できます。型安全性を持って React コンポーネントを定義する例を見てみましょう:
モジュールの拡張
人気のある JavaScript パッケージのほとんどには @types
スコープで利用可能な型定義がありますが、中には型定義がない、もしくは型定義が古いパッケージも存在します。そのような場合、TypeScript は「モジュールの拡張」という強力な機能を提供して、これらのパッケー ジに型定義を追加できます。例を見てみましょう:
この拡張された型定義をコード内で使用することができます:
モジュールの拡張は、パッケージの型定義を追加するだけでなく、既存の型定義を拡張することも可能です。例えば、window
オブジェクトに新しいプロパティを追加することができます:
そして、それをコード内で使用します:
以前の記事で、React Router ライブラリの型の問題について話しましたが、既存の型を拡張し、カスタム宣言ファイルを通じて拡張することで、その影響を克服する必要がありました。
モジュールの拡張を使用する際には、型定義の正確性を JavaScript のソースコードを慎重に検査することによって確保することが重要です。間違った型定義はランタイムエラーを引き起こす可能性があります。上記の例では、window.foo
プロパティは、window
オブジェクト上に存在する文字列でなければなりません。
グローバル拡張
時にはグローバル変数を導入するスクリプトに遭遇することがあり、そのグローバル変数の型定義を行い TypeScript コード内で使用したいと思うかもしれません。例えば、__DEV__
というグローバル変数を設定するスクリプトがある場合:
このグローバル 変数に対して、以下のように型定義を追加することができます:
これで TypeScript コード内で使用できます:
モジュール拡張とグローバル拡張を組み合わせることで、JavaScript プロトタイプの型定義を拡張することもできますが、これは一般的には推奨されていません。グローバルスコープの汚染につながる可能性があるためです。
モジュール拡張の力によってこのような拡張が可能になりますが、グローバルスコープの汚染を防ぐために注意を払うべきです。
ネストされた JavaScript ファイル
先に述べた例では、パッケージのエントリーファイルを通じてインポートが解決できることを前提としていました。しかし、一部のパッケージは、対応する型定義なしにネストされた JavaScript ファイルをエクスポートすることがあります。次の構造を持つ foo
というパッケージを考えてみましょう:
foo
パッケージは index.js
ファイルをエントリーポイントとしてエクスポートし、同時に bar
ディレクトリもエクスポートします。
foo
パッケージの型定義を拡張するには、foo.d.ts
ファイルを作成します:
ただし、TypeScript で baz.js
ファイルを インポートしようとすると、エラーが発生します:
baz.js
ファイルの型定義を拡張するには、別の baz.d.ts
ファイルを作成する必要があります:
これにより、TypeScript はモジュールとその関連する型定義を見つけることができます:
型定義を整理して保つために、型定義ファイル内でパッケージの構造を模倣することができます:
このアプローチにより、ネストされた JavaScript ファイルを処理する際にも、TypeScript コードの構造を整理し、型安全に保つことができます。