DefinitelyTyped(@types)パッケージへ型定義を追加する手順
こんにちは。開発部フロントエンドユニット所属のchiakiです。
DefinitelyTypedというパッケージにもともと存在していた型定義ファイルの修正(破壊的変更を含むバージョンアップ)を行い、発行したPull Requestがマージされました。
今回はそちらについて、経緯をまとめてご共有できればと思います。
目次
コントリビュートをしてみよう
社内のサーバサイドリプレース(express + TypeScript)において、とあるパッケージがv5.xなのに対し型定義はv2.xとなっており、期待通りの静的解析結果を得ることができていませんでした。
一旦はプロジェクトに自作の型定義ファイルを置いていましたが、せっかく作ったので@typesにもコントリビュートを行ってみようという試みになります。
こんな方におすすめとなります
- 何かしらのオープンソースプロジェクトへ貢献したいが難易度が高そうで二の足を踏んでいる方
- プロジェクトに追加したパッケージがデフォルトでTypeScript非対応かつ、@typesに型定義が存在していなかったという方
- とりあえずオープンソースプロジェクトへの貢献実績を作ってみたい方
DefinitelyTyped(@types)とは
@types
の名でも知られる、JavaScriptパッケージをTypeScriptで利用したい際に必要な型定義ファイル(~.d.ts)を集めた、TypeScriptコミュニティの中でも最大級のパッケージとなります。
JavaScriptパッケージの作成者がデフォルトでTypeScriptに対応している場合はそのままnpm等のパッケージマネージャから追加するだけで利用できますが、対応していない場合には @types
から有志によって追加された型定義を利用するか、もし追加されていない場合は自身で型定義ファイルを作成する必要があります。
※Reactでの例
1 2 3 4 |
"devDependencies": { "@types/react": "^18.2.56", "@types/react-dom": "^18.2.19", ..... |
※自作型定義の一例
1 2 3 4 5 6 |
import { WritableOptions } from 'stream'; export default class Hoge { constructor(settings: WritableOptions); someClassMethod(args: string[]): void; ..... |
Pull Requestを発行するまでの手順
ここからは実際にPull Requestを発行し、レビューを受けるまでの手順と注意点を説明していきます。
1. リポジトリのFork & Clone
GitHubのアカウントがあれば、DefinitelyTyped/DefinitelyTyped リポジトリをブラウザから自分のアカウントにForkすることが可能です。
Fork後に自身のローカルディレクトリにリポジトリをCloneし、リモートリポジトリがupstreamに設定されているかの確認を行います。
1 2 3 4 5 6 |
$ git clone git@github.com:YOUR_ACCOUNT_NAME/DefinitelyTyped.git $ git remote -v origin git@github.com:YOUR_ACCOUNT_NAME/DefinitelyTyped.git (fetch) origin git@github.com:YOUR_ACCOUNT_NAME/DefinitelyTyped.git (push) upstream https://github.com/DefinitelyTyped/DefinitelyTyped.git (fetch) upstream https://github.com/DefinitelyTyped/DefinitelyTyped.git (push) |
もし設定されていなかった場合は、以下のコマンドで設定を行います。
1 |
$ git remote add upstream https://github.com/DefinitelyTyped/DefinitelyTyped.git |
2. 修正先の依存関係のインストール
Cloneを終えましたら、実際に修正を行うパッケージの依存関係をインストールします。
types
ディレクトリの中身を実際に追加するのですが、
1 |
$ pnpm install |
などで全体をインストールしてしまうととてもサイズが大きい&時間がかかってしまうので、修正先のみをインストールする方法がおすすめとなります。
1 |
$ pnpm install --filter ./types/<<修正先のパッケージ名>> |
3. 実際に修正を行う
主に修正対象となるファイルは
types/<<パッケージ名>>/index.d.ts
types/<<パッケージ名>>/package.json
types/<<パッケージ名>>/<<パッケージ名>>.test.ts
こちらの3ファイルとなります。(パッケージによってはindex.d.ts以外の型定義ファイルが存在する場合もあります。)
3-1. types/<<パッケージ名>>/index.d.ts
型を実際に定義するファイルとなります。
主にグローバルスコープで動作するパッケージはアンビエント宣言を用いて定義を行い、モジュール形式で読み込まれるパッケージはエクスポート宣言を利用しての定義となります。
※アンビエント宣言の例
1 2 3 4 5 6 7 8 9 10 11 |
export = HogeHoge; export as namespace h2; declare namespace HogeHoge { type hogeFunctionA = (str: string) => string; type hogeFunctionB = (str: number) => number; interface HogeOptions { hogeName: string; hogeNumber: number; ..... |
※モジュール形式の例
1 2 3 4 5 6 7 8 |
import { Options } from 'fuga'; export default class Hoge { constructor(options: Options); hogeFunctionA(str: string): string; hogeFunctionB(str: number): number; ..... |
注意点として、依存関係にあるパッケージを利用する場合に、そちらが @types
に存在する場合はトリプルスラッシュディレクティブを利用し、npm
にのみ存在する場合はimport文を利用する形となります。
1 2 3 4 5 |
// Triple-Slash Directives /// <reference types="node" /> // import import { HogeIf } from 'hoge'; |
3-2. types/<<パッケージ名>>/package.json
こちらは基本的に編集する必要はないのですが、メジャーバージョンアップなどを含む場合に修正を行う形となります。
また依存関係のバージョンは、型定義を利用するパッケージと同じバージョンで定義してください。
型定義パッケージのバージョンは、リビジョン番号(最終下4桁)を9999で指定する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "name": "@types/hoge", "version": "3.0.9999", "projects": [ "https://github.com/hogeuser/hoge#readme" ], "dependencies": { "axios": "^1.6.7" }, "devDependencies": { "@types/hoge": "workspace:." }, "owners": [ { "name": "John Doe", "githubUsername": "jdoe" } ] } |
3-3. types/<<パッケージ名>>/<<パッケージ名>>.test.ts
こちらのテストはモジュールの処理についてテストするわけではなく、期待した結果が返されることをテストしてください。
1 2 3 4 5 6 7 8 9 10 |
import Hoge from "hoge"; //@ts-expect-error new Hoge({ id: 'testHogeId', username: 1111 }); // $ExpectType Hoge const hoge = new Hoge({ id: 571 username: 'testUser' }); hoge.setFugaAttribute('fuga'); // $ExpectType void hoge.getFugaAttribute(); // $ExpectType string |
4. Pull Requestの作成
修正を終えてForkしたリポジトリへのコミットをプッシュしましたら、実際にPull Requestを作成します。(masterブランチへのプッシュで大丈夫です。)
まず、upstreamに設定されているリポジトリの変更差分をForkしたリポジトリへマージします。
1 2 3 |
$ git fetch upstream $ git checkout master $ git merge upstream/master |
GitHubのPull Request作成画面で以下のテンプレートが表示されるので、ひとつずつ確認しmarkdown形式でチェックを埋めます。
1 2 3 4 5 6 7 8 9 10 11 12 |
Please fill in this template. - [ ] Use a meaningful title for the pull request. Include the name of the package modified. - [ ] Test the change in your own code. (Compile and run.) - [ ] [Add or edit tests](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/README.md#my-p ackage-teststs) to reflect the change. - [ ] Follow the advice from the [readme](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ma ster/README.md#make-a-pull-request). - [ ] Avoid [common mistakes](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/REA DME.md#common-mistakes). - [ ] [Run `pnpm test <package to test>`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ma ster/README.md#running-tests). |
また作業内容(新規追加・修正・削除)に応じて以下のテンプレートの中からひとつ選択・追加を行い、こちらもチェックを埋めていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Select one of these and delete the others: If adding a new definition: - [ ] The package does not already provide its own types, or cannot have its `.d.ts` files gener ated via `--declaration` - [ ] If this is for an npm package, match the name. If not, do not conflict with the name o f an npm package. - [ ] Create it with `dts-gen --dt`, not by basing it on an existing project. - [ ] Represents shape of module/library [correctly](https://www.typescriptlang.org/docs/handboo k/declaration-files/library-structures.html) - [ ] `tsconfig.json` [should have](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/mast er/README.md#tsconfigjson) `noImplicitAny`, `noImplicitThis`, `strictNullChecks`, and `strictFun ctionTypes` set to `true`. If changing an existing definition: - [ ] Provide a URL to documentation or source code which provides context for the suggested cha nges: <<url here>> - [ ] If this PR brings the type definitions up to date with a new version of the JS library, u pdate the version number in the `package.json`. If removing a declaration: - [ ] If a package was never on Definitely Typed, you don't need to do anything. (If you wro te a package and provided types, you don't need to register it with us.) - [ ] Delete the package's directory. - [ ] Add it to `notNeededPackages.json`. |
作成を行いますと、typescript-botというbotがPull Requestの進行状況を表すメンションを自分宛てに発行します。
Pull Request発行後〜マージされるまで
1. コードレビューの依頼
Pull Requestが発行されると、既存修正の場合は型定義パッケージのownerに対してレビュー依頼のメンションがbot経由で発行されます。
2. 必要であれば修正など
レビュアから Request Changes
で修正依頼が来た場合は修正や、Commentへのリプライなどを行います。また海外の方も多く、時差などの理由でPull Requestを発行してから数日後にレビュー開始といった状況も在るので、少し気長に待ちましょう。
Pull Request作成後にコミットがあると、botがownerに対して新しい変更があることをメンションで通知してくれます。
3. Approveされたら
何度かownerとやり取りを行い、Pull RequestがApproveされるとbotが Owner Approved
というバッジを付与します。
この状態で、Ready to merge
というコメントをPull Requestに付けると、botによるマージが自動で開始されます。
4. マージ完了
ここまで完了した場合は、自身が行う作業は特にありません。
大体数時間〜数日後にnpmjsにも反映され、パッケージマネージャによる追加が可能となります。
パッケージ追加を終えて
長くなりましたが、以上で@typesへコントリビュートを行った経緯・手順のまとめは終了となります。
最後までお読みいただきありがとうございました。