Automatically generate TypeScript type definitions for CSS Modules with full type safety and IDE autocompletion.
- 🎯 Type Safety: Get TypeScript types for all your CSS module class names
- 🔄 Automatic Generation: Generates
.d.tsfiles automatically during development - ⚡ Vite Plugin: Seamless integration with Vite's dev server and HMR
- 🎨 Naming Conventions: Multiple naming convention strategies (camelCase, dashes, custom)
- 🌳 Recursive Search: Scans entire project directory trees
- 🔧 Customizable: Flexible configuration options
- 📦 Zero Config: Works out of the box with sensible defaults
npm install css-module-type-definitions
# or
yarn add css-module-type-definitions
# or
pnpm add css-module-type-definitionsThe recommended way to use this package is as a Vite plugin:
// vite.config.ts
import { defineConfig } from 'vite';
import { pluginCssModuleTypeDefinitions } from 'css-module-type-definitions';
export default defineConfig({
css: {
modules: {
localsConvention: 'camelCase',
},
},
plugins: [
pluginCssModuleTypeDefinitions({
extension: 'module.css',
localsConvention: 'camelCase',
}),
],
});Once configured, import your CSS modules as usual and enjoy full type safety:
// Button.tsx
import styles from './Button.module.css';
// TypeScript knows about all your class names!
export const Button = () => (
<button className={styles.button}>
{/* Autocomplete works! */}
<span className={styles.icon}>✓</span>
</button>
);/* Button.module.css */
.button {
padding: 10px 20px;
background: blue;
}
.icon {
margin-right: 5px;
}This automatically generates:
/* Button.module.css.d.ts */
/* eslint-disable @typescript-eslint/naming-convention */
/*
* This file is automatically generated by css-module-type-definitions
*/
export type Classes = 'button' | 'icon';
export type Locals = { readonly [c in Classes]: string };
export declare const button: string;
export declare const icon: string;
declare const __default: Locals;
export default __default;| Option | Type | Default | Description |
|---|---|---|---|
rootDirectory |
string |
process.cwd() |
Root directory to search for CSS module files |
extension |
string |
'module.css' |
File extension pattern to match (e.g., 'module.css', 'css', 'module.scss') |
localsConvention |
string | function |
'camelCase' |
Naming convention for exported class names |
Exports both the original kebab-case name and its camelCase version:
.my-button {
}// Both available:
styles['my-button']; // ✓
styles.myButton; // ✓Exports only the camelCase version:
.my-button {
}// Only camelCase:
styles['my-button']; // ✗
styles.myButton; // ✓Converts only dashes to camelCase (preserves underscores):
.my-button {
}
.my_class {
}styles['my-button']; // ✓
styles.myButton; // ✓
styles.my_class; // ✓ (underscore preserved)Like 'dashes', but exports only the converted version:
.my-button {
}styles['my-button']; // ✗
styles.myButton; // ✓Provide your own transformation function:
pluginCssModuleTypeDefinitions({
localsConvention: (original, generated, filePath) => {
// Use SCREAMING_SNAKE_CASE
return original.toUpperCase().replace(/-/g, '_');
},
});Configure for different CSS preprocessors:
// For SCSS modules
pluginCssModuleTypeDefinitions({
extension: 'module.scss',
});
// For Less modules
pluginCssModuleTypeDefinitions({
extension: 'module.less',
});Scan only a specific directory:
pluginCssModuleTypeDefinitions({
rootDirectory: './src/components',
extension: 'module.css',
});Use a custom naming convention:
pluginCssModuleTypeDefinitions({
localsConvention: (original, camelCase, file) => {
// Add prefix based on file location
if (file.includes('/components/')) {
return `c_${camelCase}`;
}
return camelCase;
},
});- Scanning: The plugin scans your project for CSS module files matching the specified extension
- Parsing: CSS files are processed with PostCSS and CSS Modules plugins
- Extraction: Class names are extracted from the
:exportpseudo-selector - Generation: TypeScript declaration files (
.d.ts) are generated with exported types - HMR: During development, files are regenerated automatically when CSS modules change
- Node.js >= 24.0.0
- Vite (for plugin usage)
- TypeScript (recommended)
Ensure your tsconfig.json is configured to recognize CSS modules:
{
"compilerOptions": {
"types": ["vite/client"]
}
}.block {
}
.block__element {
}
.block__element--modifier {
}// With 'camelCase'
styles.block; // ✓
styles.block__element; // ✓
styles.block__elementModifier; // ✓.button:hover {
}
.button:focus {
}styles.button; // ✓ (pseudo-classes are ignored):global(.global-class) {
}
.local-class {
}// Only local classes are exported
styles.localClass; // ✓
styles.globalClass; // ✗If types aren't updating after changing CSS:
- Restart the Vite dev server
- Check that the file extension matches your configuration
- Verify the file is within the
rootDirectory
If TypeScript can't find the module:
// Add to vite-env.d.ts or global.d.ts
declare module '*.module.css' {
const classes: { readonly [key: string]: string };
export default classes;
}Ensure your IDE's TypeScript language service is running and restart it if needed.
Contributions are welcome! Please feel free to submit a Pull Request.
MIT © Phil Hill
Generate Type Definitions for CSS Modules