🐕

Vite x React x CSSModules x TypeScript環境で型安全に開発する

2021/10/13に公開

はじめに

前回までの記事で、classnames-genericsを利用して、型安全にTypeScriptでstyleを実装する方法を紹介してきました。

続の方で締めくくっているように、styleの型定義を自前で用意するのが非常に面倒でした。今回は、自動でstyleの型定義ファイルを作成するvite-plugin-sass-dtsを紹介します。

準備

vite-plugin-sass-dts をインストールする
npm i -D vite-plugin-sass-dts

vite.config.tsにプラグインを設定する

vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import sassDts from "vite-plugin-sass-dts";
import path from "path";

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "@/styles" as common;`,
        importer(...args) {
          if (args[0] !== "@/styles") {
            return;
          }

          return {
            file: `${path.resolve(
              __dirname,
              "./src/assets/styles"
            )}`,
          };
        },
      },
    },
  },
  plugins: [
    react(),
    sassDts({
      allGenerate: true,
      global: {
        generate: true,
        outFile: path.resolve(__dirname, "./src/style.d.ts"),
      },
    }),
  ],
});

コンポーネントの実装

vite を起動する
npm run dev
scss ファイルを実装して、保存する
src/App.module.scss
.header-1 {
  background-color: common.$primary;
  .active {
    background-color: black;
  }
}
src/assets/styles/_index.scss
$primary: violet;

.row {
  display: flex;
}
保存した scss ファイルと同じディレクトリに型定義ファイルが自動で作成される
src/App.module.scss.d.ts
import globalClassNames from './style.d'
declare const classNames: typeof globalClassNames & {
  readonly 'header-1': 'header-1';
  readonly 'active': 'active';
};
export = classNames;
src/style.d.ts
declare const classNames: {
  readonly 'row': 'row';
};
export = classNames;
型定義を利用してコンポーネントを実装する
src/App.tsx
import { VFC } from "react";
import styles from "./App.module.scss";
import { classNamesFunc } from "classnames-generics";

const classNames = classNamesFunc<keyof typeof styles>();
type Props = {
  active: boolean;
};

export const App: VFC<Props> = (props) => {
  return (
    <header
      className={classNames(
        styles["header-1"],
        { [styles.active]: props.active },
        styles.row
      )}
    >
      vite-plugin-sass-dts-example
    </header>
  );
};

補完もきちんと効くようになっているので、開発速度の向上が期待できます。

Discussion