Generate type-safe declaration files from CSS and SCSS modules. Works with Vite, Webpack, Rspack, and more.
- Supports
.module.css
,.module.scss
, and.module.sass
files - Works with Vite, Webpack, Rspack, and many more via Unplugin
- Generates TypeScript declaration (
.d.ts
) files alongside your stylesheets - Enables type-safe checking and autocompletion for CSS/SCSS module class names
- Only processes changed files for performance
- Handle both CSS and SCSS modules in a single plugin
- Fail builds if there are missing/invalid types
npm install --save-dev unplugin-typed-css-modules
# or
yarn add -D unplugin-typed-css-modules
# or
pnpm install --save-dev unplugin-typed-css-modules
For more detailed usage instructions, please refer to the Unplugin documentation.
-
Vite
// vite.config.ts import { defineConfig } from 'vite' import typedCssModules from 'unplugin-typed-css-modules/vite' export default defineConfig({ plugins: [ typedCssModules({ // options }), ], })
-
Webpack
// webpack.config.js /** @type {import('webpack').Configuration} */ const config = { plugins: [ require('unplugin-typed-css-modules/webpack')({ // options }), ], } module.exports = config
The plugin will now:
- Watch for changes to
.module.css
,.module.scss
, and.module.sass
files during development, and update the corresponding.d.ts
files automatically during development. - Ensure that all CSS-related types are up to date during the build step, and fail the build if any missing/mismatched types are found.
-
When committing the generated
.d.ts
files to git, to hide them from Pull Request reviews on GitHub, mark them as auto-generated using a.gitattributes
file:*.module.css.d.ts linguist-generated=true *.module.scss.d.ts linguist-generated=true *.module.sass.d.ts linguist-generated=true
-
Ignore the generated files from Prettier/other formatters:
# .prettierignore or equivalent **/*.module.css.d.ts **/*.module.scss.d.ts **/*.module.sass.d.ts
Note: Even though the files come with a
// prettier-ignore
comment, there is no way to disable Prettier from formatting a whole file, so this step is almost always necessary if you are using Prettier -
Ignore the generated files from ESLint checks:
E.g. if you are using Flat Config:
// eslint.config.js import { defineConfig } from 'eslint/config'; export default defineConfig( { ignores: [ '**/*.module.css.d.ts', '**/*.module.scss.d.ts', '**/*.module.sass.d.ts' ] }, // The rest of your config goes here... )
Note: The generated files already come with a
/* eslint-disable */
comment by default, so this step is only needed if:- You care about performance and want to avoid ESLint parsing the files altogether, or
- Your ESLint setup includes
--report-unused-disable-directives
which might mistakenly flag these files as errors
This project follows Semantic Versioning, with the sole exception that Environment Options may introduce API changes in minor/patch releases. These API changes to environment options are not necessarily breaking, but may require changes to your build setup. Any such changes will be documented in the release notes.
I am maintaining this project in my spare time, so maintaining multiple minor versions is not feasible. As such, any patch changes will not be backported to older minor versions. Please update to the latest minor version to get the latest bug fixes.
For now, the plugin accepts two options:
- Enables or disables processing of
.module.css
files. - Default:
true
- Enables or disables processing of
.module.scss
and.module.sass
files. - Default:
false
Question | Answer |
---|---|
What | Autogenerate TypeScript declaration (.d.ts ) files for your CSS and/or SCSS modules (.module.css /.module.scss /.module.sass ). |
Why | To provide a seamless developer experience when working with both CSS/SCSS modules in one plugin. |
How | A wrapper around typed-css-modules and typed-scss-modules for CSS and SCSS files, respectively. The plugin watches for changes to CSS/SCSS module files and updates the corresponding .d.ts files automatically. |
The plugin was originally created to fulfil personal needs and is designed to be simple and easy to use, with minimal configuration required. This should be able to cover the most common use cases.
In the future, I might add support for more features like further customization or performance optimizations. Feel free to open an issue or a PR if you have any suggestions or feature requests and I will try to address them as soon as possible.
Environment options are environment variables that can be set in your build environment to modify the plugin's behavior. These options are intended for assisting with one-off migrations or specific use cases, and may introduce API changes in minor/patch releases.
Currently, there is only one environment option, TCM_FORCE_BUILD
.
-
When set to
true
orTRUE
, the plugin will always regenerate all.d.ts
files during thewriteBundle
/ build step, instead of the default behavior. -
Use this to generate all
.d.ts
files the first time you add the plugin to an existing project, or if you have made bulk changes to your CSS/SCSS modules and want to regenerate all typings in one go. -
Example (Yarn + Rsbuild):
// package.json { "scripts": { "build": "rsbuild build" } }
# Without the environment variable, the build will fail if any typings are out of date TCM_FORCE_BUILD=true yarn build
If you use a build tool like Vite that watches all files (instead of just the module dependency graph), you can also use shell commands to trigger regeneration, instead of using this environment variable.
// package.json { "scripts": { "dev": "vite" } }
yarn dev # Then, in a separate terminal, "modify" all the files at once touch **/*.module.css **/*.module.scss **/*.module.sass
This plugin is built using Unplugin, so in theory, it should work with any build tool that supports unplugin, including but not limited to:
- Vite
- Webpack/Rspack
- Rollup/Rolldown
- Meta-frameworks (Astro, Nuxt, etc.)
This plugin is actively being used (and therefore validated) with:
- Vite
- Webpack (via Create React App + CRACO)
Please feel free to file an issue if you encounter any problems with using the plugin in your setup, even if you are using a build tool that is not actively being tested against.
MIT License © 2025