15日目: vite-plugin-checker を探訪

Vite は .ts ファイルのトランスパイルを行うだけで、型チェックは行わない。

別プロセスで tsc --noEmit --watch を実行して、型チェックを行えばいいのだが、最近はそれが少し不便だと思っていた。

そこで、Vite に型チェックを組み込むプラグインである fi3ework/vite-plugin-checker を試してみることに。

ボイラープレートから Vite プロジェクトを作成する。

$ npm create vite@latest hello-vite-plugin-checker -- --template react-swc-ts
$ cd hello-vite-plugin-checker
$ npm install
$ npm run dev

vite-plugin-checker をインストール。

$ npm i -D vite-plugin-checker

Get Started のドキュメント通りにプラグインに checker を追加。

diff --git a/vite.config.ts b/vite.config.ts
index 861b04b..fe50cc4 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,13 @@
 import { defineConfig } from 'vite'
 import react from '@vitejs/plugin-react-swc'
+import checker from 'vite-plugin-checker'

 // https://vitejs.dev/config/
 export default defineConfig({
-  plugins: [react()],
+  plugins: [
+    react(),
+    checker({
+      typescript: true,
+    }),
+  ],
 })

npm run dev でサーバーを起動して、適当なコンポーネントを追加。

diff --git a/src/App.tsx b/src/App.tsx
index afe48ac..af850f7 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,6 +3,19 @@ import reactLogo from './assets/react.svg'
 import viteLogo from '/vite.svg'
 import './App.css'

+type TestComponentProps = {
+  message: string;
+}
+
+const TestComponent: React.FC<TestComponentProps> = ({ message }) => {
+  return (
+    <>
+      <h1>Vite + React</h1>
+      <p>{message}</p>
+    </>
+  )
+};
+
 function App() {
   const [count, setCount] = useState(0)

@@ -16,7 +29,7 @@ function App() {
           <img src={reactLogo} className="logo react" alt="React logo" />
         </a>
       </div>
-      <h1>Vite + React</h1>
+      <TestComponent message="hello, this is a test component" />
       <div className="card">
         <button onClick={() => setCount((count) => count + 1)}>
           count is {count}

コンポーネントが表示されることを確認し、サーバーのログにも

[TypeScript] Found 0 errors. Watching for file changes.

と、型エラーが起きていないことが表示されている。

そして敢えて型エラーを起こしてみる。

diff --git a/src/App.tsx b/src/App.tsx
index e16266e..af850f7 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -4,7 +4,7 @@ import viteLogo from '/vite.svg'
 import './App.css'

 type TestComponentProps = {
-  message: string;
+  name: string;
 }

 const TestComponent: React.FC<TestComponentProps> = ({ message }) => {

すると、サーバーのログにエラーが表示され

ERROR(TypeScript)  Property 'message' does not exist on type 'TestComponentProps'.
FILE  /path/to/hello-vite-plugin-checker/src/App.tsx:10:56

    8 | }
    9 |
 > 10 | const TestComponent: React.FC<TestComponentProps> = ({ message }) => {
      |                                                        ^^^^^^^
   11 |   return (
   12 |     <>
   13 |       <h1>Vite + React</h1>

ERROR(TypeScript)  Type '{ message: string; }' is not assignable to type 'IntrinsicAttributes & TestComponentProps'.
 Property 'message' does not exist on type 'IntrinsicAttributes & TestComponentProps'.
FILE  /path/to/hello-vite-plugin-checker/src/App.tsx:32:22

   30 |         </a>
   31 |       </div>
 > 32 |       <TestComponent message="hello, this is a test component" />
      |                      ^^^^^^^
   33 |       <div className="card">
   34 |         <button onClick={() => setCount((count) => count + 1)}>
   35 |           count is {count}

[TypeScript] Found 2 errors. Watching for file changes.

画面にもエラーが表示される。便利。

なお、vitest 実行時にチェッカーを動かしたくない場合は以下のように設定すればよいとのこと。

plugins: [!process.env.VITEST ? checker({ typescript: true }) : undefined]

ESLint もチェックできるので設定を追加。

diff --git a/vite.config.ts b/vite.config.ts
index fe50cc4..a075b04 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -8,6 +8,9 @@ export default defineConfig({
     react(),
     checker({
       typescript: true,
+      eslint: {
+        lintCommand: 'eslint "./src/**/*.{ts,tsx}"',
+      },
     }),
   ],
 })

適当に eslint:recommended のルール違反になりそうなコードを追加。

diff --git a/src/App.tsx b/src/App.tsx
index e16266e..b6871d0 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -8,6 +8,8 @@ type TestComponentProps = {
 }

 const TestComponent: React.FC<TestComponentProps> = ({ message }) => {
+  debugger;
+
   return (
     <>
       <h1>Vite + React</h1>

エラー結果がレポートされた。

なお、間違っても --fix は付けないでね〜とドキュメントに記載があった。

別プロセスで動かすか Vite で動かすかなど、個人の開発スタイルに依るところが大きいので、これで万事解決というわけではないが選択肢の1つになりそうだなと思った。