TypeScript
vue.js
webpack
VisualStudioCode

JSからTSへの移行で悩んだ点の対応メモ

今回初めてJavaScript(Babel)からTypeScriptへ移行したのですが、解決に悩んだ点をいくつかピックアップしてメモしておきます
(現在も移行中なので今後もあれば追記していきます)

対象はこちらの環境になります
VSCode
webpack v3.8
Vue.js v2.5
TypeScript v2.6


awesome-typescript-loaderを使った方が速いみたいだが、.vueだと使えない
□ 対応
https://github.com/s-panferov/awesome-typescript-loader/issues/356
このissue見るとたぶん作業中
今は諦めてts-loaderにしてる


■ VSCodeの"prettier.trailingComma": "none"にしてるのに.tsの時だけカンマを付けてくる
□ 対応
tslint.jsonのprettierの設定を見ていい感じにフォーマットしてくれるようにしたかったが、できなかったので
.eslintrcのprettierを見てフォーマットするようにした

yarn add --dev prettier-eslint
"prettier.eslintIntegration": true

tslint-config-airbnbを使ってるとWarningを出す

Warning: The 'no-boolean-literal-compare' rule requires type information.
Warning: The 'strict-boolean-expressions' rule requires type information.

□ 対応
type-checkが機能していない
tslint-loaderのオプションで以下を指定する

webpack.config.js
{
  test: /\.ts$/,
  use: [
    {
      loader: 'tslint-loader',
      options: {
        typeCheck: true  // これ
      }
    }
  ],
  exclude: /node_modules/
}

以下issueで言われているように、私もビルドスピードがだいぶ落ちたので今後使うか検討した方がいいかもしれません
https://github.com/wbuchwalter/tslint-loader/issues/76


■ webpackで設定したaliasをVSCodeが認識しない

webpack.config.js
resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src')
  }
}

パスは合ってるのに、VSCode上で以下エラーとなる

 2017-12-18 16.56.03.png

□ 対応

tsconfig.jsonに以下を追加する
webpackのaliasの設定と同じようにTypeScriptにも@/*src/*であることを定義してあげるとVSCodeもちゃんと認識する

tsconfig.json
"baseUrl": ".",
"paths": {
  "@/*": [
    "src/*"
  ]
}

さらに.vueであれば以下のようにVueの型定義も必要

sfc.d.ts
declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

上記の型定義でVueファイルというのを認識させるため、import時に.vueを省略せずに書く

import Sample from '@/components/Sample.vue'

babel-plugin-istanbulを使ってコードのカバレッジを出していたので、TypeScriptだと使えなくなった
□ 対応
awesome-typescript-loaderのオプションでuseBabel: trueをすればTypeScriptを変換する時にBabelをはさめるので、babel-plugin-istanbulでも出せるのではないかと思ってる
でも今回はVueなので、上に述べたようにawesome-typescript-loaderが使えない

この後少し調べて、Reactですが公式の例で普通にts-loaderbabel-loaderを使えてました
https://github.com/Microsoft/TypeScriptSamples/blob/master/react-flux-babel-karma/webpack.config.js

webpack.config.js
{
  test: /\.ts$/,
  use: [
    {
      loader: 'babel-loader'
    },
    {
      loader: 'ts-loader',
      options: {
        appendTsSuffixTo: [/\.vue$/]
      }
    }
  ],
  exclude: /node_modules/
}
tsconfig.json
"target": "es2015"

上記設定でちゃんとbabel-plugin-istanbulを使ってカバレッジ出せました


■ TSLintのエラーにルール名が無いので、オフる時困る
□ 対応
コマンドだとformatでverboseを指定すれば出せる

tslint ./src/index.ts -t verbose

これをtslint-loaderでもできてほしいけど、オプション見ても出来なそうだった

今回はVSCodeを使っていたので、vscode-tslint-vueというプラグインを入れて解決した
https://marketplace.visualstudio.com/items?itemName=prograhammer.tslint-vue

 2017-12-18 17.34.57.png


■ vueファイルのTSLintがバグる
以下のようにしてvueファイルでもTSLintを使えるようにしている

webpack.config.json
{
  test: /\.vue$/,
  use: [
    {
      loader: 'vue-loader',
      options: {
        loaders: {
          ts: 'ts-loader!tslint-loader'
        }
      }
    }
  ]
}

しかし、Lintエラーになっていないはずなのに、こんな警告が出る
 2018-01-04 14.37.26.png

□ 対応
最初文字化けして、Lintバグってんなって思ったけど、調べてみるとVueファイル内のTSコード以外の箇所が空行と認識されていた
以下の例だとscriptタグ内以外の部分が全て空行とみなされる

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
<style>
</style>
<script lang="ts">
export default {
  name: 'App'
}
</script>

↓つまり、tslint-loader的には以下のようにみえている








export default {
  name: 'App'
}

なので、連続した空白行があるよって警告が出る
結論、Vueのサポートが不十分ということだと思うので、以下のようにして回避した

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
<style>
</style>
<script lang="ts">
/* tslint:disable:prettier */
/* tslint:enable:prettier */
export default {
  name: 'App'
}
</script>

prettierを使ってない場合は、以下のルールになると思います、たぶん
/* tslint:disable:no-consecutive-blank-lines */
/* tslint:enable:no-consecutive-blank-lines */

tslint.jsonにno-consecutive-blank-lines: falseを書いてしまうと、全体的にこのルールをオフにしてしまうので、
上記のように特定箇所のみオフした方が良いでしょう

また、TSLintを使わず、typescript-eslint-parserを使って、TypeScriptをESTree互換の形式にパースして、ESLintを使うのも良いかもしれません


■ VueファイルのtypeCheckをtrueにするとエラーになる

webpack.config.js
{
  test: /\.vue$/,
  use: [
    {
      loader: 'vue-loader',
      options: {
        loaders: {
          ts: 'ts-loader!tslint-loader?typeCheck'
        }
      }
    }
  ]
}

上記の設定でビルドすると、以下のエラーが出る
Ensure that the files supplied to lint have a .ts, .tsx, .d.ts, .js or .jsx extension.

□ 対応
tslint-loaderのtypeCheckがvue-loader上でも動作するようになるのを待つか

以下プルリクであるように、linterOptions.typeCheckという機能がprivateだが用意されているので、これが公開されるのを待つか
https://github.com/palantir/tslint/pull/1403

その他の方法を考えるか

まだ解決策を考えれてないので、解決したら追記します