問題の背景:
多くのJavaScriptエコシステムのライブラリは、独自の型を持たずにソースのjsファイルのみを提供しています。TypeScriptでは、サードパーティまたはカスタムライブラリ、さらにはグローバル変数の型を説明するために、.d.ts(declaration files)という拡張子の特別なファイルフォーマットが実装されています。これにより、任意のJSモジュールの上で型情報と型の安全性を確保する標準となりました。
問題:
サードパーティのJSモジュールの型が定義されていない場合、TypeScriptはそのようなインポートをanyとして解釈せざるを得ず、静的型付けの利点がすべて失われます:呼び出しのエラー、存在しないフィールド、不正なパラメータは論理的にはコンパイルが通ってしまい、コード実行後にのみエラーが明らかになります。また、型に関する自動補完やナビゲーションもできません。
解決策:
declaration filesを使用することで、任意のJSコードのために手動で型を説明できます:関数、クラス、オブジェクト、名前空間、さらにはグローバル定数さえも。これにより、プロジェクトは外部ライブラリの出所に関係なく型安全性を保つことができます。
コードの例:
// hello.d.ts declare module 'hello' { export function sayHello(name: string): string; } // app.ts import { sayHello } from 'hello'; sayHello('TypeScript'); // 型安全
主な特徴:
Declarationファイルにおいて関数の実装を直接宣言することはできますか?
いいえ、declarationファイルでは構造とシグネチャの宣言のみが許可され、実装はできません。関数やコンストラクタの本体を記述するとコンパイルエラーが発生します。
// できない: declare function sum(a: number, b: number) { return a + b; }
人気のあるnpmモジュールの型が元のパッケージにない場合、どこで探せばよいですか?
DefinitelyTypedリポジトリ(npmパッケージ @types/<lib>)にほとんどの人気パッケージのための最新の型定義があります。
d.tsファイルを使用してグローバル変数(importを介さずに)を記述することはできますか?
はい、ambient declarationsメカニズムを介して、例えばdeclare var VERSION: string;のように記述できます。これはwindow.X、グローバル定数や変数の記述に便利です。
** ネガティブケース プロジェクトでタイピングがないJSライブラリが使用されています。開発者はd.tsファイルを忘れ、anyを介してAPIにアクセスします。ライブラリの更新時にバグが発生します:古い呼び出しが壊れますが、コンパイラはそれに気付きません。
長所:
短所:
** ポジティブケース 現在のライブラリのための独自のd.tsファイルが作成され、シグネチャは最新の状態で保たれ、自動補完とIDEナビゲーションが使用されます。
長所:
短所: