本記事はcloudpack あら便利カレンダー 2019の記事です
タイトルが難しい。何をしたいのか伝えられた自信がない
以前 VS CodeでJavascriptの型判定を行う - Qiita という記事を書きました。
この記事では触れていなかったのですが、これどうやるんだろう?っていう内容がありました。
やりたいこと
- 依存モジュールの
type
やinterface
で定義された情報をローカル変数の型に指定したい - 指定した型に基づいてVisual Studio Codeに補完してほしい
- Node.jsで
mongoclient触っている時に思ったので、これを例にします
クエリを投げる時にどんなクエリが投げられるか忘れるので、型補完してほしい。
そのためにFilterQuery
というtype
が用意されているのでJavascriptでもそれを利用したい。
// こんな感じで指定したら
/** @type {FilterQuery} */
const query = {
// ここで色々補完してほしい
}
補完してみる
Typescriptなら簡単
普通にimportして型を指定すれば良いです。
import { FilterQuery, MongoClient } from "mongodb";
interface User {
name: string
}
const client = new MongoClient("");
const query: FilterQuery<User> = {
}
こうしておけば、query
の中身を編集する際にキャプチャのように候補を出してくれます。
これと同じことをJavascriptでしたい
Javascriptの場合
色々試してみました
requireで読み込み
Javascriptの場合はrequire
で読み込めるので、以下でいけるかなと思ったらダメでした。
const mongo = require('mongodb')
/** @type {mongo.FilterQuery} */
const query = {}
requireで読み込んだ場合はFilterQuery
が存在しない(参照できない)状態でした。
const client = new mongo.MongoClient("");
は見えるんですけどね
Javascriptでは本来存在しないのでexport type ***
やexport interface ***
は見えないようにしている?
というわけで、require
では無理でした。
importで読み込み
JavascriptのES6を使えば同様にimport
できるので、これを使えば補完はできます。
import { FilterQuery, MongoClient } from "mongodb";
/** @type {FilterQuery} */
const query = {}
ただし、動かせません(意味なし)。
Node.jsではCommonJSで動作するので、ECMA Scriptのモジュールシステムは使えないです。
(function (exports, require, module, __filename, __dirname) { import { FilterQuery } from "mongodb";
^
SyntaxError: Unexpected token {
動かすためには.mjs
という拡張子にする必要があるようです。(Node.js(v8.5.0以降)でBabelやwebpackを利用せずにimport/exportを利用する - Qiita)
今回はこの方法はやめておきます
JSDocにimportを埋め込む(成功)
じゃあどうするか、ということになるんですが、JSDocのtype
の中にimport
を埋め込めば補完対象としてくれました。
コードは以下です。
//@ts-check
const mongo = require('mongodb')
class User {
constructor() {
/** @type {string} */
this.name = undefined;
}
}
const client = new mongo.MongoClient("");
/** @type {import("mongodb").FilterQuery<User>} */
const query = {
name: {
}
};
ちゃんと補完も効きました
一応目標達成。ちょっと面倒ですが
問題点
補完を効くようにする、という意味では成功だったのですが、問題点がありました。
jsdocコマンドでJSDocを生成しようとするとエラーを吐きました。
ERROR: Unable to parse a tag's type expression for source file type.js in line 10 with tag title "type" and text "{import("mongodb").FilterQuery<User>}": Invalid type expression "import("mongodb").FilterQuery<User>": Expected "!", "=", "?", "[]", "|", or end of input but "(" found.
ここにimportが来ることなんて想定してないよ、とのことです。残念
まだ調べきれてないのですが、なんとか設定とかで回避できないですかね?
JSDocあまり詳しくはないので、詳しい方いたら教えてください。
まとめ
Javascriptで型補完を支援する方法を書きました。
真面目に書く時はTypescriptを使うようになったので、どうしても必要というほどではなかったんですが、もうちょっとというところだったので色々試してみました。
Javascriptメインだという方は使ってみてください。
で、もっといい方法があったら教えてください
参考
VS CodeでJavascriptの型判定を行う - Qiita
Node.js(v8.5.0以降)でBabelやwebpackを利用せずにimport/exportを利用する - Qiita