CommonJS+Classなライブラリの型定義を書く

とあるCommonJSのライブラリをTypeScriptのプロジェクトで使おうと思って、いつも通りインストールしてimportしたら、型定義がないと怒られた。

「ならば書いて解決しましょう、そんなに難易度高くないでしょ」と高を括り書き始めたが、どうもハマらない。

丸2日ほどかかって編み出した魔術じみたやり方で解決できたので、今回はそれを伝授しようと思う。


TL;DR


経緯・解説

まずオレオレ型定義を作るときには、@typesというディレクトリをtsconfig.jsonと同レベル以下に置けば読みに行ってくれる。
その中に[module_name].d.tsだったり[module_name]/index.d.tsなりを作るわけだ。

その記法なんだけど、ざっくり次の2通りが見られるのね。

  • declare module '[libname]'
  • export as namespace [libname]

何故かはまだ調べてないけど、後者は全く役に立たなかった。前者は反応はあったけど、中括弧 (curly braces) を付けると壊れる。

これが単にメソッド定義が無いだけならクラス定義をexportしてやればいいんだけど(TL;DRの失敗例みたいな)、それだとanyになってしまい、ただIDEの赤線を消しただけになってしまう。

そして(探し方が下手なのか?)classをmodule.exports = {}でまとめている例がDefinitelyTypedではなかなか見当たらない。

悩みに悩んだ挙げ句、ふと脳裏をよぎったのが、ES2020で入ったimport()を使った方法。
Next.jsを書いてた時に(今も書いてるけど)、component単位でSSRを無効にするために使ったDynamic Importでやったことがあった。
(ちなみにimport()Promiseを返すので、awaitなりメソッドチェーンなりでresolveしてやる必要がある)

module.exports = Fuga;のスタイルは目にするけど、Objectでまとめている例が見つからず、とりあえずという事でKeyは自分で書くことに。動けばいいのよ

これでちゃんと動くと思うんだけど、何かスマートじゃないよね、という感が…
何か良い方法があればtwitterあたりで教えて下さい。

コメントする