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
```

```json
"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`のオプションで以下を指定する

```js: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が認識しない

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

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

<img width="592" alt=" 2017-12-18 16.56.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/07f8c566-242c-92bf-933e-2a0630357a5c.png">

□ 対応

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

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

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

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

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

```js
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-loader`と`babel-loader`を使えてました
https://github.com/Microsoft/TypeScriptSamples/blob/master/react-flux-babel-karma/webpack.config.js

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

```json: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

<img width="503" alt=" 2017-12-18 17.34.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/dbdbc34f-8c41-c1e6-6873-3bb1881d1639.png">

---

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

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

しかし、Lintエラーになっていないはずなのに、こんな警告が出る
<img width="1062" alt=" 2018-01-04 14.37.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/2500b4cb-4979-655d-322c-2b1ebf937e64.png">

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

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

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

```html








export default {
  name: 'App'
}

```

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

```html
<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にするとエラーになる

```js: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

その他の方法を考えるか

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