Programmingフロントエンド開発者

TypeScriptにおけるDeclaration Filesとは何か?自分自身のd.tsファイルを書くべき時と理由は?外部JSモジュールのためのユーザー定義の型記述をどのように構造化するのか?

Hintsage AIアシスタントで面接を突破

返答。

問題の背景:

多くの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'); // 型安全

主な特徴:

  • 実装(元のJSコード)からシグネチャと型構造の説明を分離します;
  • サードパーティや古いビルドにも厳格な型付けを導入できます;
  • .d.tsファイルでは実装は禁止されており、シグネチャ/説明のみが許可されています。

ひっかけ質問。

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、グローバル定数や変数の記述に便利です。

型に関するエラーとアンチパターン

  • d.tsファイルに関数やクラスの本体を書くこと;
  • 不完全または古いシグネチャを記述し、実際の構造と対立を招くこと;
  • 同じモジュール/グローバル変数に異なる型定義を接続し、型の対立を招くこと。

実生活の例

** ネガティブケース プロジェクトでタイピングがないJSライブラリが使用されています。開発者はd.tsファイルを忘れ、anyを介してAPIにアクセスします。ライブラリの更新時にバグが発生します:古い呼び出しが壊れますが、コンパイラはそれに気付きません。

長所:

  • スピーディなスタート、追加の説明は不要。

短所:

  • 隠れたエラー、不明な動作、大規模なコードでのデバッグの難しさ。

** ポジティブケース 現在のライブラリのための独自のd.tsファイルが作成され、シグネチャは最新の状態で保たれ、自動補完とIDEナビゲーションが使用されます。

長所:

  • 完全な型安全性、APIの変更時にすぐにエラーが目に見える;
  • 開発の加速、新しい開発者の参加が深くJSコードを学ぶことなく可能。

短所:

  • d.tsファイルの別々の管理、JSライブラリの更新時に同期を保つ必要があります。