型定義ファイル(.d.ts)と@types
この章の目次開く
JavaScriptで書かれたライブラリをTypeScriptから使うとき、型情報が必要です。型定義ファイル(.d.ts)がその橋渡しをします。
学習者ライブラリを入れたら「型定義が見つかりません」って怒られた…。@types/... って何者なの?
先生JSで書かれたライブラリには型情報がない。@types パッケージはコミュニティが作った「後付けの型定義」だよ。ライブラリ本体が最初からTSで書かれていれば不要なんだけどね。
.d.tsファイルとは
.d.ts ファイルは型情報だけを記述したファイルです。実行時のJavaScriptコードは含まず、TypeScriptコンパイラが型チェックに使います。
// example.d.ts
export declare function formatDate(date: Date, format: string): string;
export declare const VERSION: string;declare キーワードは「この関数/変数は別の場所で実装されている」ことを表します。.d.ts は実装ではなく契約書のようなものです。
@typesパッケージ — DefinitelyTyped
JavaScriptで書かれたライブラリに型定義がない場合、コミュニティがDefinitelyTypedリポジトリで型定義を管理しています。
npm install --save-dev @types/react @types/node @types/expressTypeScriptは node_modules/@types/ 配下を自動的に参照するため、インストールするだけで型が効きます。
型定義が同梱されているライブラリ
すべてのライブラリに @types が必要なわけではありません。ライブラリ本体に .d.ts が含まれている場合は不要です。
# @types 不要 — ライブラリ本体に型定義が含まれている
npm install zod # TypeScriptで書かれている
npm install axios # .d.ts が同梱されている
npm install date-fns # TypeScriptで書かれている見分け方は、ライブラリの package.json に "types" または "typings" フィールドがあるかどうかです。
// axiosの package.json(抜粋)
{
"types": "./index.d.ts"
}型定義がないライブラリへの対処
@types パッケージも存在しないライブラリの場合、declare module で最低限の型定義を書きます。
// src/types/some-legacy-lib.d.ts
declare module 'some-legacy-lib' {
export function doSomething(input: string): void;
export default class Client {
constructor(apiKey: string);
fetch(url: string): Promise<unknown>;
}
}すべてのAPIを詳細に型付けする必要はありません。自分が使う部分だけ定義すれば十分です。
学習者型定義を書くのが面倒なときは any で逃げてもいい?
先生最初は any で通して動くようにして、あとから少しずつ型を付けていくのが現実的。ただし any を使った箇所はコメントや TODO で記録しておくと、後で見つけやすいよ。
最小限の型定義で any を使う場合:
// src/types/some-legacy-lib.d.ts
declare module 'some-legacy-lib' {
const content: any;
export default content;
}グローバル型定義
プロジェクト全体で使う型を global.d.ts に定義できます。
// src/types/global.d.ts
// 環境変数の型定義
declare namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
NEXT_PUBLIC_API_URL: string;
NODE_ENV: 'development' | 'production' | 'test';
}
}
// Window オブジェクトの拡張
interface Window {
gtag: (...args: unknown[]) => void;
}
環境変数の型を定義しておくと、process.env.DATABASE_URL が string として推論され、undefined チェックが不要になります。
型定義ファイルの配置
型定義ファイルは tsconfig.json の include に含まれるパスに置きます。
src/
types/
global.d.ts ← グローバル型定義
some-legacy-lib.d.ts ← ライブラリの型定義
api-response.ts ← アプリの型定義(通常の .ts)ちゃんと使うためのポイント
-
.d.tsは型情報だけのファイル。実装は含まない @types/xxxはコミュニティ管理の型定義。ライブラリ本体に型があれば不要- 型定義がないライブラリは
declare moduleで最低限の型を書く - 環境変数や
Windowの拡張はグローバル型定義で対応する - 自アプリの型定義は
.ts、外部ライブラリの型付けは.d.tsで書く
参考リンク
- TypeScript Handbook — Declaration Files(英語) — 型定義ファイルの公式ガイド
- DefinitelyTyped — @typesパッケージの供給元リポジトリ
