はじめに
この投稿は、学習の備忘録として書いています。typeof import("...")で、モジュールがexportしているものの型をまとめて取る書き方を整理します。動作を確認したバージョンはTypeScript 5.9.3です。
1. typeof importが表す型
例として、次のファイルを考えます。
// math.ts
export const PI = 3.14;
export function add(a: number, b: number) {
return a + b;
}
typeof import("./math")は、このモジュールがexportしているものを、オブジェクト型として表します。
type MathModule = typeof import("./math");
// {
// PI: 3.14;
// add: (a: number, b: number) => number;
// }
PIとaddの型を一つずつ手で書かなくても、モジュール全体の型を一度に取れます。
2. 値のimportとの違い
普通のimportは、実行時にモジュールを読み、使える値を受け取ります。
import { add } from "./math";
add(1, 2);
typeof import("./math")は型だけです。動くaddは手に入りません。
type MathModule = typeof import("./math");
// MathModuleは型なので、次のように呼ぶことはできない
// MathModule.add(1, 2);
// 'MathModule' only refers to a type, but is being used as a value here.
値として使いたいときは通常のimport、型としてモジュール全体を表したいときにtypeof import、という違いです。
3. 値のimportなしで、型注釈に使う
同じファイルでimport * as mathしていれば、引数の型はtypeof mathでも書けます。typeof importが効くのは、そのファイルでは値としてimportせず、型だけ参照したいときです。
// useMath.ts(mathを値としてimportしない)
export function useMath(math: typeof import("./math")) {
return math.add(1, 2);
}
// main.ts(実体はここで読む)
import * as math from "./math";
import { useMath } from "./useMath";
useMath(math);
-
useMath.ts…typeof import("./math")で引数の型だけを参照する。実行時にはmath.tsを読まない -
main.ts…import * as mathで実体を読み、useMathに渡す -
useMath内のmath.addは、渡された実体を呼んでいる
まとめ
-
typeof import("...")は、モジュールがexportしているものをオブジェクト型として表します。 - 普通の
importは値を取り、typeof importは型だけを取ります。 - モジュール全体の型が欲しいとき(型注釈など)に使います。実体は、別途
importしたり引数で渡したりします。