ライブラリの構造

大まかに言うと、宣言ファイルをどのように構造化するかは、ライブラリがどのように消費されるかによって異なります。JavaScriptでライブラリを消費するために提供する方法はたくさんあり、それに対応する宣言ファイルを作成する必要があります。このガイドでは、一般的なライブラリパターンを識別する方法と、そのパターンに対応する宣言ファイルを記述する方法について説明します。

主要なライブラリ構造化パターンの各タイプには、テンプレートセクションに対応するファイルがあります。これらのテンプレートから始めて、より早く作業を開始できます。

ライブラリの種類を識別する

まず、TypeScriptの宣言ファイルが表現できるライブラリの種類を確認します。各ライブラリの種類がどのように使用され、どのように記述されるかを簡単に示し、実世界の例となるライブラリをいくつかリストします。

ライブラリの構造を識別することは、その宣言ファイルを記述する最初のステップです。使い方コードの両方に基づいて構造を識別する方法のヒントを提供します。ライブラリのドキュメントと編成によっては、どちらか一方が他方よりも簡単な場合があります。より快適な方を使用することをお勧めします。

何を探すべきか?

型を付けようとしているライブラリを見ているときに自問する質問。

  1. ライブラリをどのように入手しますか?

    たとえば、npmからのみ、またはCDNからのみ取得できますか?

  2. どのようにインポートしますか?

    グローバルオブジェクトを追加しますか?requireまたはimport/exportステートメントを使用しますか?

さまざまな種類のライブラリの小さなサンプル

モジュールライブラリ

ほとんどすべての最新のNode.jsライブラリはモジュールファミリに該当します。これらのタイプのライブラリは、モジュールローダーを備えたJS環境でのみ機能します。たとえば、expressはNode.jsでのみ機能し、CommonJSのrequire関数を使用してロードする必要があります。

ECMAScript 2015(ES2015、ECMAScript 6、ES6とも呼ばれます)、CommonJS、RequireJSは、モジュールインポートするという同様の概念を持っています。たとえば、JavaScript CommonJS(Node.js)では、次のように記述します。

js
var fs = require("fs");

TypeScriptまたはES6では、importキーワードが同じ目的を果たします

ts
import * as fs from "fs";

通常、モジュールライブラリのドキュメントには、これらの行のいずれかが含まれています。

js
var someLib = require("someLib");

または

js
define(..., ['someLib'], function(someLib) {
});

グローバルモジュールと同様に、UMDモジュールのドキュメントでこれらの例を見つけることがあるため、コードまたはドキュメントを確認してください。

コードからモジュールライブラリを識別する

モジュールライブラリには、通常、少なくとも以下のいずれかが含まれます。

  • require または define の無条件呼び出し
  • import * as a from 'b';export c; のような宣言
  • exports または module.exports への代入

めったに以下は含まれません。

  • window または global のプロパティへの代入

モジュールのテンプレート

モジュールには、module.d.tsmodule-class.d.tsmodule-function.d.tsmodule-plugin.d.ts の 4 つのテンプレートがあります。

まず、すべての動作方法の概要について、module.d.ts をお読みください。

次に、モジュールが関数のように呼び出すことができる場合は、module-function.d.ts テンプレートを使用します。

js
const x = require("foo");
// Note: calling 'x' as a function
const y = x(42);

モジュールが new を使用して構築できる場合は、module-class.d.ts テンプレートを使用します。

js
const x = require("bar");
// Note: using 'new' operator on the imported variable
const y = new x("hello");

インポート時に他のモジュールを変更するモジュールがある場合は、module-plugin.d.ts テンプレートを使用します。

js
const jest = require("jest");
require("jest-matchers-files");

グローバルライブラリ

グローバルライブラリとは、グローバルスコープからアクセスできるライブラリ(つまり、importの形式を使用せずに)のことです。多くのライブラリは、使用するために1つ以上のグローバル変数を単に公開しています。たとえば、jQuery を使用している場合、$ 変数はそれを参照するだけで使用できます。

ts
$(() => {
console.log("hello!");
});

通常、グローバルライブラリのドキュメントには、HTML スクリプトタグでライブラリを使用する方法に関するガイダンスが記載されています。

html
<script src="http://a.great.cdn.for/someLib.js"></script>

今日、最も一般的なグローバルアクセス可能なライブラリは、実際には UMD ライブラリとして記述されています(下記参照)。UMD ライブラリのドキュメントは、グローバルライブラリのドキュメントと区別するのが困難です。グローバル宣言ファイルを作成する前に、ライブラリが実際には UMD ではないことを確認してください。

コードからグローバルライブラリを識別する

グローバルライブラリのコードは通常非常にシンプルです。グローバルの「Hello, world」ライブラリは、次のようになります。

js
function createGreeting(s) {
return "Hello, " + s;
}

または、次のようになります。

js
// Web
window.createGreeting = function (s) {
return "Hello, " + s;
};
// Node
global.createGreeting = function (s) {
return "Hello, " + s;
};
// Potentially any runtime
globalThis.createGreeting = function (s) {
return "Hello, " + s;
};

グローバルライブラリのコードを見ると、通常は次のようになります。

  • トップレベルの var ステートメントまたは function 宣言
  • window.someName への 1 つ以上の代入
  • documentwindow などの DOM プリミティブが存在するという前提

以下は表示されません

  • requiredefine などのモジュールローダーのチェックまたは使用
  • var fs = require("fs"); 形式の CommonJS/Node.js スタイルのインポート
  • define(...) の呼び出し
  • ライブラリを require またはインポートする方法を説明するドキュメント

グローバルライブラリの例

通常、グローバルライブラリを UMD ライブラリに変換するのは簡単であるため、グローバルスタイルで記述された人気のあるライブラリはほとんどありません。ただし、小さくて DOM を必要とするライブラリ(または依存関係がないライブラリ)は、グローバルなままである可能性があります。

グローバルライブラリテンプレート

テンプレートファイル global.d.ts は、ライブラリ myLib の例を定義します。「名前の競合を防ぐ」の脚注を必ずお読みください。

UMD

UMD モジュールとは、モジュールとして(インポートを介して)またはグローバルとして(モジュールローダーのない環境で実行した場合)使用できるモジュールのことです。Moment.js など、多くの人気のあるライブラリがこの方法で記述されています。たとえば、Node.js または RequireJS では、次のように記述します。

ts
import moment = require("moment");
console.log(moment.format());

一方、プレーンなブラウザ環境では、次のように記述します。

js
console.log(moment.format());

UMDライブラリを識別する

UMD モジュールは、モジュールローダー環境の存在を確認します。これは、次のような簡単に判別できるパターンです。

js
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["libName"], factory);
} else if (typeof module === "object" && module.exports) {
module.exports = factory(require("libName"));
} else {
root.returnExports = factory(root.libName);
}
}(this, function (b) {

ライブラリのコードで、特にファイルの先頭に typeof definetypeof window、または typeof module のテストが表示される場合は、ほとんどの場合 UMD ライブラリです。

UMD ライブラリのドキュメントでは、require を示す「Node.js での使用」の例と、スクリプトをロードするための <script> タグを使用する「ブラウザでの使用」の例もよく示されています。

UMDライブラリの例

現在、ほとんどの人気ライブラリは UMD パッケージとして入手できます。例としては、jQueryMoment.jslodash などがあります。

テンプレート

module-plugin.d.ts テンプレートを使用します。

依存関係を消費する

ライブラリには、いくつかの種類の依存関係がある可能性があります。このセクションでは、宣言ファイルにインポートする方法を示します。

グローバルライブラリへの依存関係

ライブラリがグローバルライブラリに依存している場合は、/// <reference types="..." /> ディレクティブを使用します。

ts
/// <reference types="someLib" />
function getThing(): someLib.thing;

モジュールへの依存関係

ライブラリがモジュールに依存している場合は、import ステートメントを使用してください。

ts
import * as moment from "moment";
function getThing(): moment;

UMDライブラリへの依存関係

グローバルライブラリから

グローバルライブラリがUMDモジュールに依存している場合は、/// <reference types ディレクティブを使用してください。

ts
/// <reference types="moment" />
function getThing(): moment;

モジュールまたはUMDライブラリから

モジュールまたはUMDライブラリがUMDライブラリに依存している場合は、import ステートメントを使用してください。

ts
import * as someLib from "someLib";

UMDライブラリへの依存関係を宣言するために /// <reference ディレクティブを使用しないでください!

脚注

名前の衝突の回避

グローバル宣言ファイルを作成する際に、グローバルスコープで多くの型を定義できることに注意してください。多くの宣言ファイルがプロジェクトにある場合、解決できない名前の衝突が発生する可能性があるため、これは強く推奨されません。

従うべき簡単なルールは、ライブラリが定義するグローバル変数によって名前空間化された型のみを宣言することです。たとえば、ライブラリがグローバル値 'cats' を定義している場合、次のように記述する必要があります。

ts
declare namespace cats {
interface KittySettings {}
}

しかし、そうではない

ts
// at top-level
interface CatsKittySettings {}

このガイダンスは、宣言ファイルユーザーを壊すことなく、ライブラリをUMDに移行できることも保証します。

モジュール呼び出しシグネチャに対するES6の影響

Expressなどの多くの一般的なライブラリは、インポートされると呼び出し可能な関数として公開されます。たとえば、典型的なExpressの使用法は次のようになります。

ts
import exp = require("express");
var app = exp();

ES6に準拠したモジュールローダーでは、トップレベルオブジェクト(ここではexpとしてインポート)はプロパティのみを持つことができます。トップレベルのモジュールオブジェクトは、決して呼び出し可能にすることはできません。

ここでの最も一般的な解決策は、呼び出し可能/構築可能なオブジェクトのdefaultエクスポートを定義することです。モジュールローダーは通常、この状況を自動的に検出し、トップレベルオブジェクトをdefaultエクスポートに置き換えます。tsconfig.jsonで"esModuleInterop": trueを設定している場合、TypeScriptはこれを処理できます。

TypeScriptドキュメントはオープンソースプロジェクトです。これらのページを改善するために、プルリクエストを送信してご協力ください ❤

このページの貢献者
MHMohamed Hegazy (57)
OTOrta Therox (17)
DRDaniel Rose (3)
Llilichao (1)
MFMartin Fischer (1)
12+

最終更新日: 2024年3月21日