Nuxt.jsとtypescriptの最小構成

追記。この記事の内容は古いです。無事に公式サポートされました。

---

地獄。早く(まともに)公式サポートして。
こんなにつらいならjsでいいんじゃないかと諦めかけた。

# 構成

```:ディレクトリ構成
.
├── nuxt.config.js
├── package.json
├── pages
│   └── index.vue
├── store
│   ├── index.ts
├── tsconfig.json
└── tslint.json
```

## package.json

```json:package.json
{
  "scripts": {
    "dev": "nuxt"
  },
  "devDependencies": {
    "@types/node": "^10.12.18",
    "ts-loader": "^5.3.3",
    "typescript": "^3.2.2"
  },
  "dependencies": {
    "nuxt": "^2.3.4",
    "nuxt-property-decorator": "^1.3.1",
    "nuxt-typescript": "^0.11.0",
  }
}
```

devDependenciesとdependenciesの切り分けはよくわからんので、[nuxt-community/typescript-template](https://github.com/nuxt-community/typescript-template)を参考にした。

[nuxt-typescript](https://www.npmjs.com/package/nuxt-typescript)は、modules/typescript.jsを自分で書かなくてもいいやつ。公式度合いがどれくらい心配なのかは不明。

## nuxt.config.js

```javascript:nuxt.config.js
module.exports = {
  modules: ["nuxt-typescript"]
}
```

[nuxt-typescript](https://www.npmjs.com/package/nuxt-typescript)のとおり。

## tsconfig.json

```json:tsconfig.json
{
  "compilerOptions": {
    "jsx": "preserve",
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "baseUrl": ".",
    "paths": {
      "~/*": ["./*"],
      "@/*": ["./*"]
    },
    "strict": true,
    "sourceMap": true,
    "noUnusedLocals": true,
    "experimentalDecorators": true
  }
}
```

[nuxt-typescript](https://www.npmjs.com/package/nuxt-typescript)のとおり。

## pages/index.vue

```vue:pages/index.vue
<template>
  <section>
    <h1>hello {{ message }}</h1>
    <button @click="increment">{{ counter }}</button>
  </section>
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator';

@Component
export default class extends Vue {
  message = "world"

  get counter() {
    return this.$store.state.counter;
  }

  increment() {
    this.$store.commit('increment');
  }
}
</script>
```

適当にdataとstoreを使うサンプル。

## store/index.ts

```typescript:store/index.ts
export const state = () => ({
  counter: 0
})

export const mutations = {
  increment (state: any) {
    state.counter++;
  }
}
```

適当にmutationを使ったサンプル。

# インストール手順

1. 上記ディレクトリ構成を配備
2. npm install
3. npm run dev


# 様々な地雷

本当に様々な地雷があってもう眠いので適当に書きます

## [nuxt-community/typescript-template](https://github.com/nuxt-community/typescript-template)は動かない
そのまま動かしてもだめ。パッケージを全部アップデートしてもだめ。

## tsconfig.jsonで入力ファイルが無いよというエラー
プロジェクト内に一つでも.tsファイルが無いと正常に動作しません。

## .vueファイルのscript部の「@Component」のアットマークでunexpectedとか
[tsconfig.jsonで入力ファイルが無いよというエラー](#tsconfig.jsonで入力ファイルが無いよというエラー)こいつのせい。これがほんとにハマった

## npm-install時にUnexpected end of JSON input while parsing

```Unexpected end of JSON input while parsing near '...","@types/convert-sou'```

これが出たら```npm cache clean --force```しろって[ここの人たち](https://github.com/vuejs-templates/webpack/issues/990)が言ってるし、私もやったら治った。

## storeのなかにxxxx.tsを作っても読み込んでくれない
これもハマったけど、最初からやり直したらいつの間にか治った。よくわからん。
もしかしたらtsとjsのファイルを共存できないのかもしれない。

## [nuxt-typescript](https://www.npmjs.com/package/nuxt-typescript)を使うのはbetterか
全く自信がない。[nuxt-community/typescript-template](https://github.com/nuxt-community/typescript-template)が動かない以上何を信じたら良いのやら。
最もメンテナンスされててディファクトスタンダードなのは何なんだろう。
こいつは[nuxt-community/typescript-template](https://github.com/nuxt-community/typescript-template)のissueを見てたら見つけたやつ。

## storeの分割もできるよ

こういうやつも問題なくできた

```
├── store
│   ├── mutations.ts
│   └── state.ts
```

[公式ドキュメント](https://ja.nuxtjs.org/guide/vuex-store#%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%83%A2%E3%83%BC%E3%83%89)に書いてある機能です。

## vueファイルのstyleとscriptの分割もできるよ

```
├── pages
│   ├── index.vue
│   └── script.ts
```

```vue:pages/index.vue
<template>
  略
</template>

<script lang="ts" src="./script.ts"></script>
```

[公式ドキュメント](https://jp.vuejs.org/v2/guide/single-file-components.html#%E9%96%A2%E5%BF%83%E3%81%AE%E5%88%86%E9%9B%A2%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)に書いてある機能です。

ちなみに、このようにscript部を.tsファイルにすると、vscodeのデコレータを使うことのWarningが消える

## 型定義

さっきやっと動いたばかりだしもう朝方だからギブアップ。
多分[nuxt-community/typescript-template](https://github.com/nuxt-community/typescript-template)のindex.d.tsとかパクれば動くとおもう。vuexの型定義については、[この記事](https://qiita.com/potato4d/items/c9c0c8e674f20c85948a#vuex-%E3%82%92%E4%BD%BF%E3%81%86%E5%A0%B4%E5%90%88)が非常に詳しい。
vuexとかapiが残念なので、あんまり型定義を頑張りすぎないほうが良いと思われる。