Webpack loader that works as a css-loader drop-in replacement to generate TypeScript typings for CSS modules on the fly
Install via npm
npm install --save-dev typings-for-css-modules-loader
Just like any other loader you can specify options e.g. as query-params
Any option that your installed version of css-loader supports can be used and will be passed to it.
As your fellow css-developer may tend to use characters like dashes(
-) that are not valid characters for a typescript variable the default behaviour for this loader is to export an interface as the default export that contains the classnames as properties.
A cleaner way is to expose all classes as named exports, this can be done if you enable the
test: /\.css$/ loader: 'typings-for-css-modules?modules&namedExport'
As mentioned above, this requires classnames to only contain valid typescript characters, thus filtering out all classnames that do not match /^\w+$/i. (feel free to improve that regexp)
In order to make sure that even classnames with non-legal characters are used it is highly recommended to use the
camelCase-option as well, that - once passed to the css-loader - makes sure all classnames are transformed to valid variables.
test: /\.css$/ loader: 'typings-for-css-modules?modules&namedExport&camelCase'
using the following css:
will generate the following typings file:
css-loader exports mappings to
exports.locals which is incompatible with the
namedExport-option unless paired with
style-loader. They move the exported properties from
exports making them required for
namedExport to work, and
namedExport required for them to work. Always combine usage of
style-loader with the
To silence the loader because you get annoyed by its warnings or for other reasons, you can simply pass the "silent" query to the loader and it will shut up. e.g.:
test: /\.css$/ loader: 'typings-for-css-modules?silent'
To add a "banner" prefix to each generated
*.d.ts file, you can pass a string to this option as shown below. The prefix is quite literally prefixed into the generated file, so please ensure it conforms to the type definition syntax.
test: /\.css$/ loader: 'typings-for-css-modules?banner="// This file is automatically generated by typings-for-css-modules.\n// Please do not change this file!"'
webpack.config as is just instead of using
its important you keep all the params that you used for the css-loader before, as they will be passed along in the process
webpackConfigmoduleloaders:test: /\.css$/ loader: 'css?modules'test: /\.scss$/ loader: 'css?modules&sass';
webpackConfigmoduleloaders:test: /\.css$/ loader: 'typings-for-css-modules?modules'test: /\.scss$/ loader: 'typings-for-css-modules?modules&sass';
Imagine you have a file
~/my-project/src/component/MyComponent/myComponent.scss in your project with the following content:
typings-for-css-modules-loader will generate a file
~/my-project/src/component/MyComponent/myComponent.scss.d.ts that has the following content:
namedExport with the
namedExport as well as the
camelCase options the generated file will look as follow:
Example in Visual Studio Code
If you encounter the following errors:
error TS1192: Module '"xxxxx/xxxx/src/style.sass"' has no default export.
maybe you should export the styles as following:
import * as styles from './style.sass';
As the loader just acts as an intermediary it can handle all kind of css preprocessors (
The only requirement is that those preprocessors have proper webpack loaders defined - meaning they can already be loaded by webpack anyways.
The loader uses
css-loader(https://github.com/webpack/css-loader) under the hood. Thus it is a peer-dependency and the expected loader to create CSS Modules.
Webpack rebuilds / builds slow
As the loader generates typing files, it is wise to tell webpack to ignore them. The fix is luckily very simple. Webpack ships with a "WatchIgnorePlugin" out of the box. Simply add this to your webpack plugins:
plugins: [ new webpack.WatchIgnorePlugin([ /css\.d\.ts$/ ]), ... ]
css is the file extension of your style files. If you use
sass you need to put
sass here instead. If you use
stylus or any other style language use their file ending.
Typescript doesnt find the typings
As the webpack process is independent from your typescript "runtime" it may take a while for typescript to pick up the typings. Any hints on how this could be fixed deterministically are welcome!