Vue3 の SFC (<script setup>) を TypeScript で使用する時に VSCode の lint エラーを解決する手順

# はじめに

`vue3` から導入された SFC(`<script setup>`) 、とても便利ですよね。
ただ、プロジェクトを作った段階では SFC を使うと `VSCode` でエラー表示になったりします。
試行錯誤して解決策を見つけたのですが、自分の`Google Keep`メモに保存しておくよりこちらに公開した方が有益かなと思ったので、記事にしようと思います。

# 手順

## VSCode の volar をインストール

`vue2` の頃は `Vetur` を使っていたのですが、 `Vetur` は SFC の書き方に対応していないので、代わりに `Volar` を使います。

https://v3.ja.vuejs.org/guide/typescript-support.html

## vue プロジェクトの作成

プロジェクトを作成し、VSCodeで開きます。

```
npx @vue/cli create test
```

## (確認用ファイルの作成)

挙動を見るため、`component` の中に適当なSFCファイルを作って、`App.vue` から参照しておきます。

```components/test.vue
<script setup lang="ts">
import { ref } from "vue";

defineProps<{
  name: string;
}>();

const hello = ref("hello");
</script>

<template>
  <div>{{ hello }} {{ name }}</div>
</template>

<style lang="stylus" scoped></style>
```

```App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <Test name="Tom" />
  <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</template>

<script lang="ts">
import { defineComponent } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
import Test from "./components/test.vue";

export default defineComponent({
  name: "App",
  components: {
    HelloWorld,
    Test,
  },
});
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

この段階では、`defineProps` が定義されていないというエラーが出てビルドできません。

```
error  in ./src/components/test.vue

Module Error (from ./node_modules/eslint-loader/index.js):

path\to\components\test.vue
  2:1  error  'defineProps' is not defined  no-undef
```

`import { defineProps } from "vue"` を記述する事でも解決しますが、 `defineProps` はコンパイラマクロなので、そもそも `import` は不要なはず。
これを直していきます。

## .eslintrc.js に追記

以下を参考に、`env` に `"vue/setup-compiler-macros": true` を追加し、`override` も設定します。

https://eslint.vuejs.org/user-guide/#faq

```.eslintrc.js
module.exports = {
  root: true,
  env: {
    node: true,
    "vue/setup-compiler-macros": true, // 追加
  },
  extends: [
    "plugin:vue/vue3-essential",
    "eslint:recommended",
    "@vue/typescript/recommended",
    "@vue/prettier",
    "@vue/prettier/@typescript-eslint",
  ],
  parserOptions: {
    ecmaVersion: 2020,
  },
  rules: {
    "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
  },
  overrides: [ // 追加
    {
      files: ["*.vue"],
      rules: {
        "no-unused-vars": "off",
        "@typescript-eslint/no-unused-vars": "off",
      },
    },
  ],
};
```

残念ながら、これだけだとエラーが出ます。

```
ERROR  Failed to compile with 1 error

Syntax Error: Error: .eslintrc.js:
        Environment key "vue/setup-compiler-macros" is unknown
    at Array.forEach (<anonymous>)
```

## eslint-plugin-vue のバージョンを変更

前項でのエラーは、`eslint-plugin-vue` の不具合のようで、バージョン8で修正されているようです。

https://github.com/vuejs/eslint-plugin-vue/issues/1695

`vue cli` でインストールされた `eslint-plugin-vue` はバージョン7になっているので、これを8にアップグレードします。
package.jsonに記載されいてるバージョンを書き換えて、インストールし直します。

```package.json
{
  ...
  "devDependencies": {
    ...
    "eslint-plugin-vue": "^8.0.0",
    ...
  }
  ...
}
```

**追記**

後日、「依存関係が合わない！」という旨のエラーが出たのですが、`@vue/eslint-config-typescript`を`^10.0.0`へアップグレードしたら解決しました。

```
npm i
```

## (VSCode 再起動)

ここまでで手順は完了しており、ビルドもできるようになるのですが、エディタ上でエラーや警告が出ている場合は `VSCode` を再起動すると解決すると思います。

# おわりに

`.eslintrc.js` の `override` で、未使用の変数や関数に関するエラーを出さないようにルールを追加しているのですが、`pug` を使用する環境では、これが無いと `<script>` で宣言して `<template>` の中でしか使用していない変数が警告を出します。

<img width="500px" alt="pug.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321330/a6c14ae5-98ef-96d5-758a-bc4f782aec50.png">

HTMLで記述する場合は `override` は不要かと思うので、適宜調整して使ってください。