36
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DefinitelyTyped に型定義を新規追加してみた

Last updated at Posted at 2020-04-22

まえがき

  • DefinitelyTyped とは、言わずと知れた TypeScript 用の型定義リポジトリ。
  • 昨今、特にフロントエンドでは TypeScript を使うのが当たり前となったが、まだまだ過去の遺産、型定義すらない JavaScript ライブラリも多い。
  • 型定義がなければ自前で書く必要があり、せっかく書いたのなら公開して、世界のどこかで悲しむ誰かを救いたい。
  • 「型定義を書く」とは、基本的に公式ドキュメントを TypeScript に変換することである。
  • つまり、基本的な TypeScript の知識と根性さえあれば書くことができる。
  • なので、「とりあえず OSS コントリビューターとしての実績作りしたい」みたいな下心を満たすのにも DefinitelyTyped は打ってつけなのである。

以下、先人達のナレッジ + 自分用に整理した 型定義を新規追加する場合の 手順を書き残す。

環境

  • macOS: 10.12
    • CPU: 1.8 GHz
    • Mem: 8 GB
  • node: v13.12.0
  • npm: 6.14.4
  • 対象 package: jexcel (*)

(*) jexcel とは

準備

(手順中の具体的な数字 (size など) は、2020-04-12 時点のもの。参考まで。)

# git clone。約 15 分で完了。
$ git clone git clone https://github.com/${MY_NAME}/DefinitelyTyped.git
# > Receiving objects: 100% (486652/486652), 542.02 MiB | 683.00 KiB/s, done.

# いつもの
$ npm i

# 何はともあれ test を試す。6681 packages の test が実行される。約 3 分で完了。
$ npm t

# 何はともあれ lint を試す。`For a good example package, see base64-js.` とのことなので。
$ npm run lint base64-js

# 型定義のベースを作成する。`For a good example package, see base64-js.` とのことなので。(*1)
$ cp -r types/base64-js types/jexcel
$ mv types/jexcel/base64-js-tests.ts types/jexcel/jexcel-tests.ts

# 後はお好みのエディタで。
$ code .

(*1) 型定義のベースの作成方法について

  • 基本的には『「dts-gen」を使って型定義の雛形を生成せよ』とプルリクテンプレートに書かれている。
  • しかし、dts-gen は「Browser support in progress! This is not quite ready yet.
  • つまり、ブラウザ JavaScript 実行環境特有の値 (document など) を使う package には非対応である。
    • jexcel はこれに該当するため、雛形は上記手順の通り cp で作成した。

雛形の書き換え

$ diff -r types/base64-js types/jexcel
Only in types/base64-js: base64-js-tests.ts
diff -r types/base64-js/index.d.ts types/jexcel/index.d.ts
1,3c1,3
< // Type definitions for base64-js 1.2
< // Project: https://github.com/beatgammit/base64-js
< // Definitions by: Peter Safranek <https://github.com/pe8ter>
---
> // Type definitions for jexcel 3.9
> // Project: https://github.com/paulhodel/jexcel
> // Definitions by: arx-8 <https://github.com/arx-8>
Only in types/jexcel: jexcel-tests.ts
diff -r types/base64-js/tsconfig.json types/jexcel/tsconfig.json
5c5,6
<             "es6"
---
>             "es6",
>             "dom"
21c22
<         "base64-js-tests.ts"
---
>         "jexcel-tests.ts"
  • tsconfig.json
    • 今回の package では DOM 特有の型 (HTMLElement型など) が登場するため、 compilerOptions.lib"dom" を追加した。

型定義を書く

  • 型定義を書く。
  • 型なき世界への怒りと悲しみを燃やして、根性で書く。
  • 公式のドキュメントを参照したり、console.log(typeof value)console.log(value.constructor) を駆使して、闇を切り開く。

ツール

  • 以下の 2 コマンドをエラーがなくなるまで叩く&修正。
# lint
npm run lint jexcel

# formatter
npm run prettier -- --write types/jexcel/**/*.ts

lint の rule の無効化について

  • 特にレガシーな package の場合、そう簡単に全ての型定義を書かせてくれないことが多い。
  • 例えば、デフォルトでは ban-typesFunction 型がエラーになる。
    • もちろん極力修正したいが、時間的制約などで全て対応できないこともある。
    • 「とりあえず関数なのはわかるが、正確なシグネチャがわからない」場合に Function 型を使いたい。
    • そのような場合は、// tslint:disable-next-line ban-types のラインコメントによる disable が推奨らしい。
      • tslint.json should be present and it shouldn't have any additional or disabling of rules. Just content as { "extends": "dtslint/dt.json" }. If for reason the some rule need to be disabled, disable it for that line using // tslint:disable-next-line [ruleName] and not for whole package so that the need for disabling can be reviewed.
  • 完璧な定義より、まずは全体像の把握・本当に必要な定義の完成を目指した方が、コスパがよいと思う。きっと Done is better than perfect.

サンプルコードを書く

  • 型定義が正しいこと・予期せぬ型エラーがないことを示すため、ファイル名 ${PACKAGE_NAME}-tests.ts にサンプルコードを書く
  • このコードは、実際に処理が実行されるものではない。
  • ただ型チェックのみが実行される。
  • 公式のサンプルコードをコピペ・足りない型宣言を追記する等で、なるべくカバレッジを高めておく。

型定義の動作確認

UnitTest

npm t

自分で使ってみる

  • もしその package を使用しているプロジェクトがあるなら、型定義を実際に使ってみる。
  • プロジェクトの node_modules/@types/ 配下に index.d.ts ファイルを置けば、 npm i @types/* した時と同じように動作する。
    • 例えば、今回は ${MY_PROJECT}/node_modules/@types/jexcel/index.d.ts に定義を置いて、動作確認した。

プルリクエスト

作成

  • Make a pull request」の手順に従う。
  • Folk した自分の DefinitelyTyped のリポジトリに、プルリクエストを作成する。
  • プルリクエストテンプレートのチェックリストを埋める。
  • merge の from/to を確認する。
    • from: 自分の型定義追加・修正ブランチ
    • to: DefinitelyTyped/DefinitelyTyped リポジトリの master ブランチ
  • 「Create pull request」

これで作業完了。お疲れさまでした。
以下、実際に作成したプルリク。
(ミス・拙い英語・時間都合で省いた定義、諸々恥ずかしいレベルだが、自戒も込めて晒しておく)
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/43837

プルリク作成後の時系列

  • 基本、プルリク作成で作業完了である。
    • もちろんレビュー指摘があった場合は、状況に応じて対応が必要。
  • ただし結構待ちがあり、何か手順見落としたのではとハラハラした。
  • 参考までに、今回の時系列を書いておく。

2020-04-12 20:25 JST: プルリク作成
2020-04-12 21:22 JST: typescript-bot がやってきて、コメントと適切なラベルを付与
2020-04-14 08:12 JST: レビュー指摘 (1 回目) を頂く
2020-04-15 07:31 JST: レビュー指摘 (1 回目) の反映を push
2020-04-18 05:38 JST: レビュー指摘 (2 回目) を頂く(すまぬ・・・すまぬ・・・)
2020-04-18 14:22 JST: レビュー指摘 (2 回目) の反映を push
2020-04-21 06:26 JST: merged
2020-04-22 05:54 JST: typescript-bot がやってきて、npm に publish

  • 計 10 日掛かった。
  • 1 発で通れば 3 日、レビュー 1 回で通れば 6 日くらいか。

その他ナレッジ

参考プルリクエスト探しには、GitHub label を使う

  • 例えば、「型定義の新規追加のプルリクエスト」を探したい場合は、ラベル「New Definition」を見てみる。

感想

  • DefinitelyTyped、巨大なリポジトリなので「git clone や vscode で開いたりしたら PC がぶっ壊れるんじゃないか」なんて謎の先入観を持っていたが、全く無問題だった。 git と vscode は偉大。
  • 英語は、読む。
    • 諦めて、根性で読むしかない。Google翻訳・DeepL翻訳を駆使して、公式は読む。
    • 変に日本語訳や噛み砕いた(古い)情報を探しても「最新版は違っていた」なんてこともある。(じゃあこの記事も書くなよという話ではあるが)
    • もちろん、雰囲気を知るため簡単な日本語記事から読み始めるのはアリ。しかし、最後はやはり「公式を読め」。
  • 型安全な世界を目指して、今後ともぜひ TypeScript & DefinitelyTyped やっていきましょう。
36
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?