kintone の型定義全部書く
こんにちは。
今回は、kintone の型定義全部書こうと思います。
どういうことかと言いますと、kintone
オブジェクトの TypeScript 型定義を書いてエディタ上での開発体験を最高にしてやろうって話ですね。
ちなみにこの記事は、kintone アドベントカレンダー 2021 その2の19日目の記事です。
更新状況
- 12/20: 1日遅れで初回投稿、未完成
kintone
オブジェクトと型定義
kintone には JavaScript や CSS を用いて UI をカスタマイズする機能があることは皆さんご存知かと思われます。
そういったカスタマイズをサポートするための機能として kitone JavaScript API というものが用意されており、利用する際にはグローバル変数として存在する kintone
オブジェクト経由で各 API にアクセスします。
現代においては、TypeScript を用いてカスタマイズ/プラグイン開発をされる方も多いと思われますが、ここで重要なのが型定義の存在です。
npm で配布されているパッケージであれば、API の型定義が同梱されていたり、あるいは Definitely Typed(いわゆる@types
)で配布されていたり、大抵の場合何かしらの手段で型定義を用意することができます。
npm パッケージになっていない場合、例えば実行環境のグローバルに存在する API を利用する際にも、Node.js なら@types/node
、chrome ブラウザ拡張なら@types/chrome
などのように、Definitely Typed に型定義が存在し、それを利用することができる場合もあります。DOM の API とかだとそもそも TypeScript 自体が定義を持ってたりしますね。
さてkintone
は後者のパターンですが、@types/kintone
は存在していないので、何らかの手段で型定義を用意してやる必要があります。手書きとか。
詳しい方なら@kintone/dts-gen
というツールをご存知かと思われます。
kintone
オブジェクトの型定義 + アプリに合わせた型定義の生成をしてくれるツールで、カスタマイズを TypeScript を用いて書く時に重宝している方も多いんじゃないでしょうか。[1]
また、REST API のリクエストの送信用にkintone.api
という API も存在していますが、TypeScript で書かれたクライアントである@kintone/rest-api-client
を利用することでdts-gen
を利用するときよりもさらに詳細な型定義を利用することも出来ます。
さて、型定義があることの利点とは何でしょうか。
もちろん大元の目的は静的型検査によるコードの安全性の担保だと思いますが、恐らく型推論による補完が実現する圧倒的開発体験が楽しくて、皆様 TypeScript を利用されてることかと思います。
今回の僕の目的は、kintone
の型定義を1から全部書くことで、自らの TypeScript 力を高めつつ、型推論によりバシバシ補完が効く世界に没頭し、そして大いなる kintone の恵みへの感謝を高める、まあそういう感じです。(?)
デモ
案ずるより産むが易し、百聞は一見に如かず、とにかく VSCode 上での補完の様子を見ていただきましょう。話はそれから。
リポジトリはこちら
kintone & types ということで、名前は kypes。意図せず sk◯pe っぽくなってしまいました。
現状 npm パッケージとしては公開していないので、README.md の手順にしたがってセットアップします。
この先yarn
を利用しますが、お手元の環境に合わせてnpm
等に読み替えてください。
まずはgit clone
とyarn link
$ cd path/to/your/workspace
$ git clone https://github.com/shintaroNagata/kypes.git
$ cd kypes
$ yarn build
$ yarn link
そうしたら、適当なディレクトリを作成して、yarn link kypes
します。
$ cd ../
$ mkdir test-kypes
$ cd test-kypes
$ yarn init -y
$ yarn link kypes
VSCode が賢すぎるのか、補完の動作見るだけなら僕の手元だと TypeScript なしでも動いてるんですが、一応設定しておきます。
執筆時点の最新バージョン(v4.5.4)で動作を確認しています。
$ yarn add -D typescript
$ yarn tsc --init
tsconfig.json
は、補完を見るだけならとりあえず生成されたまま用いて問題ないです。
さて、実際の補完の様子を見てみましょう。
先ほど作成したディレクトリと同じ場所に適当な.ts
ファイルを作成し、先頭でパッケージを import
します
import "kypes"
これでkintone
に関する型定義が global に読み込まれます。
tsconfig.json
に特別な記述をする必要はありません。
おもむろにkintone.
と入力してみましょう。
はい、補完されそうですね。
API の返り値にも、もちろん補完が効きます。
この辺りまでは@kintone/dts-gen
でも実現できる部分なので、もう少し複雑な例を見てみようと思います。
イベント処理
カスタマイズでよく使う API といえば、やはりkintone.events.on
でしょうか。
第一引数はイベント名を入力しますが、もちろん補完が効きます。
イベントの種類に合わせて、イベントオブジェクトのプロパティも補完されます。
複数のイベントに対するハンドラの登録でも、ちゃんと補完が効きます。
上の例では、両方のイベントに共通のプロパティが補完候補に出てきています。
うっかり片方にしかないプロパティにアクセスすると、ちゃんと怒られますね。
そういう時にはevent.type
の値で分岐してあげれば、ちゃんと絞り込み型推論が適用されます。
イベント名自体の入力補完は効きませんが、change
イベントにもしっかり対応しています。
フィールドとかも補完されそうな雰囲気です。(フィールド名と対応させたりはまだ未実装ですが……)
REST API の実行
もう1つ、kintone.api
の例を見ていきましょう。
API パス、リクエストパラメータ、レスポンスのプロパティの補完などに対応しています。
地味なこだわりポイントとして、↑のように$id
、$revision
への補完が効いたりします。
URL 指定の場合にも(もちろんkintone.api.url
を利用した場合にも)対応しています。
bulkRequest.json
のような、比較的複雑な API でもちゃんと補完が効いてます。
その他、紹介したいところは色々あるのですが、記事上では限界があるのでこのくらいにしておきます。
気になる方は色々触って試してみてください。
技術的な話
本来はここの話が本題なのですが、既に投稿遅れてしまっているので後日追って書きます……
今後
色々と書きましたが、正直まだまだ色々と不完全です。
「型定義全部書く」とかタイトルに書きましたが、全然全部書けてません。
型定義の沼は深く、そして kintone は壮大でした。
続きでやりたいことリストとしては
- JSDoc対応
- 型定義とは直接関係ないのですが、エディタ上の補完と同じくらい API の Usage が出ることって重要だと思うんです。知らんけど。
- ちなみに現状でも一部の API は対応してます。
- ページごとの型定義
- ページの種類ごとに利用できる API って変わるので、その辺りを上手く解決したいなーと検討中
- イベントハンドラの返り値の制約
- Promise に対応してるかとか、
return event
してるかとか - あんまり調査できてないので実装に至らず。多分そんなに複雑じゃないので(フラグ)、やればできるんだろうなと思いつつ、少し様子見です。
- Promise に対応してるかとか、
- 型定義の洗練
- 単なるリファクタ目的というよりは、複雑な型をつけている関係上、エラーが出た時の可読性が怪しい。パッケージの性質上、エディタ上の表示こそが「機能」たりうるので、上手くその辺りのバランスを取った記述にしたい。
- アプリごとの型定義への対応
- 生成までは出来なくても、
form/fields.json
の返り値をローカルのファイルに持っておくと、そこから自動的に型判定される、とかやってみたいですね。 - とはいえ今の型定義だと独自のアプリ構造を差し込む口がないので、設計を練り直さないと上手く行かなそう。
- 生成までは出来なくても、
辺りです。引き続き、型定義全部書くまで頑張ろうと思います。
-
自分は普段カスタマイズというよりは、プラグインとかブラウザ拡張を作ることが多いので、実はあんまり使ったことがないです。 ↩︎
Discussion
これ凄いですね!
試してみましたけど、イベントハンドラの種類別にプロパティが変わるのとか見事です!感動しました!!
現状
event.record(s)
は汎用的なレコードオブジェクトしか入らないようですね。プラグイン開発にはとても良さそうですが、アプリの個別カスタマイズを想定すると、@kintone/dts-gen
で作った型をジェネリクスで渡せるようになると超ありがたいです。ひとまずこんな風にすれば何とか行けますね。
これ実務で普通に使いたいレベルなので、ぜひNPM公開してくださいませ!
というか、もうこれを
@types/kintone
にしちゃいましょうよw