Fully typed css modules with typed-css-modules
I really like CSS modules, mainly because you're just writing plain CSS instead of some bespoke JavaScript solution. This makes it future proof and portable.
We can also give another level of developer experience with CSS modules by strongly typing (at least strong for CSS) our import.
The issue: “Loose typing” when using CSS Modules in TypeScript
When it comes down to it, all CSS modules is doing is renaming your classes automatically to scope them. Simple in theory. What that means is the class names are key to the process.
I was looking through my old posts and found one where I was dealing with differences in typing between NextJS and Vite CSS modules. But generally, CSS modules are typed loosely like:
It's generally correct but could result in errors that CSS just ignores (like a class not existing) but JavaScript has issues with.
For example, take a look at this import:
styles.myButton could be undefined, which won't crash the app in this situation, but in other situations would need to be accounted for.
It becomes more extreme when building things like a thing system. I can't put details here, but we would import all CSS modules into a single theme object and provide as context. This became problematic when we didn't know the specific types.
Benefits of typing your css
We get a number of benefits when we type our CSS more strongly. Things like:
- Auto-completion of class names (because TS doesn’t know the keys)
- Compile-time checking of mis-typed class names (
styles.myButonwill compile) - Confidence that all the class names you wrote in CSS are visible and correct in TS, and that there are no “dead” names in the CSS that are forgotten.
The fix: Generating specific typings with typed-css-modules
Enter typed-css-modules (and building on this package, typed-scss-modules). This package will look at our CSS files and build *.d.ts files to describe them to TypeScript.
It comes as a CLI package that is easy enough to figure out. However, I wanted it to run automatically whenever I saved a file. It wasn't as obvious as I first thought, but in VS Code (or other VS Code flavored editors like Cursor) we can define a background action to handle it.
Automating it in VS Code
You can make VS Code automatically start a background watcher every time you open the project.
In your workspace, create or update .vscode/tasks.json with something like this:
Here’s what’s happening:
--watchkeeps the process running and automatically updates type definitions as you edit CSS files.runOn: "folderOpen"makes VS Code start this task automatically whenever you open the workspace.isBackground: truekeeps it running quietly in the background.reveal: "silent"hides the terminal output unless there’s an error.
The result: every time you open your project in VS Code, the typed-css-modules watcher kicks in automatically. As you add or change CSS classes, the corresponding .d.ts files stay up-to-date — no manual commands, no plugins, no remembering anything.
Conclusion
If your CSS Modules are still typed like this:
then you’re missing one of TypeScript’s best benefits: compile-time safety.
By adding typed-css-modules — and letting VS Code run it automatically in the background — you bring your CSS into the type system, gain better tooling support, and make your refactors safer.
It’s a small setup that makes your codebase feel more polished, reliable, and cohesive.