JavaScriptでも静的な型が求められるようになりTypeScriptやFlowが使われるようになってきました。
しかし、それらが無かったころのJavaScriptのコードやトランスパイラを使わずに開発している人はいてると思います。
この記事はコードの変更なしでJSDocのみで型検査をする方法を紹介します。
TL;DR
- JSDocの型定義で型チェックをする
- TypeScriptのallowJsとcheckJsを使う
- 必要に応じてd.tsをインストールする
JSDocの型定義
TypeScriptやFlowが登場するより前からJSDocは存在します。JavadocやPHPDocのJavaScript版のようなものです。
そのJSDocは型定義が書けるようになっています。
エディタによってはJSDocの型定義で型のチェックを行ってくれることもあります。
JSDocについては@use JSDocにすべて載っています。
JSDocの型定義の書き方は以下のような感じです。
/**
* @param {number} a
* @param {number} b
* @return {number}
*/
function add(a, b) {
return a + b;
}
JSDocの型定義を使って型のチェックをする
型のチェックにはTypeScriptを使います。トランスパイルは行いません。
TypeScriptの準備
まずはTypeScriptをインストールします。
npm install --save-dev typescript
次にtsconfig.jsonを作成します。
npx tsc --init
allowJsとcheckJsオプションを有効にする
自動生成されたtsconfig.jsonのallowJs
とcheckJs
プロパティを有効にします。
{
// "allowJs": true,
// "checkJs": true,
}
以下のようにします。
{
"allowJs": true,
"checkJs": true,
}
トランスパイル結果を出力しない
トランスパイルは行いません。と述べましたが、厳密にはトランスパイル結果を出力しないが正しいです。
tsconfig.jsonのnoEmit
を有効にします。
{
// "noEmit": true,
}
以下のようにします
{
"noEmit": true,
}
型チェックしたいディレクトリを指定する
tsconfig.jsonのinclude
を指定します。
{
"include": [
"src/"
]
}
逆にチェックしたくないディレクトリも指定できます。
node_modules
以下のチェックも不要だと思いますので、ここで指定した方が良いでしょう。
{
"exclude": [
"dist/",
"node_modules"
]
}
型定義をインストールする
TypeScriptには有名なライブラリやフレームワーク用に型定義ファイルが用意されています。
例えばExpressの型定義ファイルは@types/expressです。
npm install --save-dev @types/express
import express from "express";
// 途中略
app.use(errorHander);
/**
* @param {express.Request} req
* @param {express.Response} res
* @param {express.NextFunction} next
*/
function errorHander(req, res, next) {
res.end("Error");
}
他にも型定義ファイルはたくさんあるのでTypeSearchから探してみてください。
型チェックを実行する
npm-scriptsから実行できるようにpackage.json
に記載しておくとよいでしょう。
{
"scripts" {
"typecheck": "tsc"
}
}
npm run typecheck
試しに以下のようなソースコードで型チェックが正しく行われているか確認してみましょう。
import {add} from './calc';
console.log(add("1", 2));
/**
*
* @param {number} a
* @param {number} b
* @return {number}
*/
export function add(a, b) {
return a + b;
}
実行してみます。
npm run typecheck
以下のようなエラーが表示されました。
> tsc
src/index.js:3:17 - error TS2345: Argument of type '"1"' is not assignable to parameter of type 'number'.
3 console.log(add("1", 2));
index.js
を修正します。
import {add} from './calc';
console.log(add(1, 2));
実行してみます。
npm run typecheck
> tsc
エラーがなくなりました。
add
関数の引数にnumber
型で渡すとエラーになりませんが、string
型を渡すとエラーになるので、正しくJSDocの型定義から型チェックできていることがわかります。
最後に
既にJSDoc書いているのであれば既存のコードは変更せずに済みます。またJSDocに型定義書いてFlowやTypeScriptの型定義も書いてって冗長になることもありません。
もし、既存のコードを修正したくないけど型チェックを行いたいといった場合は今回の記事の内容が参考になれば幸いです。
これから新規で開発する場合は素直にTypeScriptで書いた方がいいと思います。またコードの変更が許容されるならFlowで段階的に型チェックすると良いかと思います。
いずれにせよ型チェックはしたほうが品質は上がると思います。
最後までお読み頂きありがとうございました。質問や不備があればコメント欄またはTwitter(@shisama_)までお願いいたします。