JavaScript
TypeScript

TypeScriptを徐々に導入する

TypeScriptは部分的に導入することが出来ないと思ってFlowtypeを導入したが、出来るぞ!という指摘を頂いたので、調べた。

--allowjsオプション

tscの実行時に--allowjsを付けるだけだった。tsconfig.jsonの場合、compilerOptions.allowJstrueを設定すればよい。

検証用のディレクトリを作って、typescriptをインストールする。

$ mkdir allow-options
$ cd allow-options

$ echo "{}" > package.json
$ yarn add -D typescript

tsconfig.jsonを書く。(TypeScriptにあまり詳しくないので自信は無い)compilerOptions.allowJstrueにする。

tsconfig.json
{
  "compilerOptions": {
    "allowJs": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "outDir": "./lib/"
  },
  "include": [
    "./src/"
  ]
}

src/a.tssrc/b.jsを書く。TypeScriptからJavaScriptの関数を読み込む。

src/a.ts
import b from './b';

export default function a(arg1: number, arg2: number): number {
  return b(arg1) + b(arg2);
}
src/b.js
export default function b(num) {
  return num * 2;
}

tscを実行する。普通にコンパイルが通る!lib/以下にa.js, b.jsとソースマップが出力される。

$ tsc
# => 何も出ない

# a.js, b.jsが出力されている
$ ls lib
./        ../       a.js      a.js.map  b.js      b.js.map

--allowjs falseを付けてtscを実行する。(もちろん、tsconfig.jsonallowJsを書き換えてもOK)実行するとエラーが表示され、lib/以下を見ると、a.jsだけがある。

# クリアする
$ rm -r lib

# 実行。エラーが出る
$ tsc --allowjs false
src/a.ts(1,15): error TS6143: Module './b' was resolved to '/xxxx/xxxx/xxxx/allowjs-option/src/b.js', but '--allowJs' is not set.

# lib/a.jsは出力されている
$ ls lib
./        ../       a.js      a.js.map

src/a.tsを下記のように書き換える。

src/a.ts
import b from './b';

export default function a(arg1: number, arg2: number): number {
  return b(arg1, arg2) + b(arg1, arg2);
}

tscを実行するとエラーが出る。引数の数はちゃんと見ているみたいですね。

$ tsc
src/a.ts(4,10): error TS2554: Expected 0-1 arguments, but got 2.
src/a.ts(4,26): error TS2554: Expected 0-1 arguments, but got 2.

追記: --checkJsオプション

コメント欄で@cotttpanさんに「--checkJsオプションを使うとJSDocの型を見てくれるぞ!」と教えていただいたので、試してみた。

Type Checking JavaScript Files · Microsoft/TypeScript Wiki

src/b.jsにJSDocのコメントで関数の引数と返り値の型を記述する。

src/b.js
/**
 * @param {number} num
 * @return number
 */
export default function b(num) {
  return num * 2;
}

src/a.tsを下記のように書き換え、numberで受け取った引数を文字列に変換してb関数に渡す(ちょっと無理やりですが)

src/a.ts
import b from './b';

export default function a(arg1: number, arg2: number): number {
  return b(arg1 + "") + b(arg2 + "");
}

tsc--checkjsオプションを追加して、実行する。tsconfig.jsonで指定する場合は、compilerOptions.checkJsをtrueにする。

$ tsc --checkjs
src/a.ts(4,12): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
src/a.ts(4,27): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'

ちゃんと型をチェックしてくれていますね!ドキュメントを見ると関数の引数・返り値以外にもJSDocで型注釈できるようで、よさそう。

@cotttpan さん、ありがとうございました。

おわり

普通に出来ました。--allowJsオプションはTypeScript 1.8からの機能で、--checkJsオプションは2.3からの機能のようです。