Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm trying to import a theme from a CSS module but TypeScript gives me a "Cannot Find Module" error and the theme isn't applied on runtime. I think there's something wrong with my Webpack config but I'm not sure where the problem is.
I'm using the following tools:
"typescript": "^2.0.3"
"webpack": "2.1.0-beta.25"
"webpack-dev-server": "^2.1.0-beta.9"
"react": "^15.4.0-rc.4"
"react-toolbox": "^1.2.3"
"node-sass": "^3.10.1"
"style-loader": "^0.13.1"
"css-loader": "^0.25.0"
"sass-loader": "^4.0.2"
"sass-lint": "^1.9.1"
"sasslint-webpack-plugin": "^1.0.4"
Here is my webpack.config.js
var path = require('path');
var webpack = require('webpack');
var sassLintPlugin = require('sasslint-webpack-plugin');
module.exports = {
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: 'http://localhost:8080/',
filename: 'dist/bundle.js',
devtool: 'source-map',
resolve: {
extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js'],
module: {
rules: [{
test: /\.js$/,
loader: 'source-map-loader',
exclude: /node_modules/,
enforce: 'pre',
test: /\.tsx?$/,
loader: 'tslint-loader',
exclude: /node_modules/,
enforce: 'pre',
test: /\.tsx?$/,
loaders: [
'react-hot-loader/webpack',
'awesome-typescript-loader',
exclude: /node_modules/,
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
test: /\.css$/,
loaders: ['style', 'css']
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
plugins: [
new sassLintPlugin({
glob: 'src/**/*.s?(a|c)ss',
ignoreFiles: ['src/normalize.scss'],
failOnWarning: false, // Do it.
new webpack.HotModuleReplacementPlugin(),
devServer: {
contentBase: './'
and my App.tsx
where I'm trying to import:
import * as React from 'react';
import { AppBar } from 'react-toolbox';
import appBarTheme from 'react-toolbox/components/app_bar/theme.scss'
// local ./theme.scss stylesheets aren't found either
interface IAppStateProps {
// No props yet
interface IAppDispatchProps {
// No state yet
class App extends React.Component<IAppStateProps & IAppDispatchProps, any> {
constructor(props: IAppStateProps & IAppDispatchProps) {
super(props);
public render() {
return (
<div className='wrapper'>
<AppBar title='My App Bar' theme={appBarTheme}>
</AppBar>
export default App;
What else is required to enable typesafe stylesheet module importing?
TypeScript does not know that there are files other than .ts
or .tsx
so it will throw an error if an import has an unknown file suffix.
If you have a webpack config that allows you to import other types of files, you have to tell the TypeScript compiler that these files exist. To do so add a declaration file in which you declare modules with fitting names.
The content of the module to declare depends on the webpack loader used for the file type. In a webpack configuration that pipes *.scss
files through sass-loader → css-loader → style-loader, there will be no content in the imported module, and the correct module declaration would look like this:
// declaration.d.ts
declare module '*.scss';
If the loaders are configured for css-modules just extend the declaration like this:
// declaration.d.ts
declare module '*.scss' {
const content: Record<string, string>;
export default content;
–
–
–
–
–
Here is a complete configuration that works for me (I just spent an hour of painful trial and error on this - in case anybody runs into the same issues):
TypeScript + WebPack + Sass
webpack.config.js
module.exports = {
//mode: "production",
mode: "development", devtool: "inline-source-map",
entry: [ "./src/app.tsx"/*main*/ ],
output: {
filename: "./bundle.js" // in /dist
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: [".ts", ".tsx", ".js", ".css", ".scss"]
module: {
rules: [
{ test: /\.tsx?$/, loader: "ts-loader" },
{ test: /\.scss$/, use: [
{ loader: "style-loader" }, // to inject the result into the DOM as a style block
{ loader: "css-modules-typescript-loader"}, // to generate a .d.ts module next to the .scss file (also requires a declaration.d.ts with "declare modules '*.scss';" in it to tell TypeScript that "import styles from './styles.scss';" means to load the module "./styles.scss.d.td")
{ loader: "css-loader", options: { modules: true } }, // to convert the resulting CSS to Javascript to be bundled (modules:true to rename CSS classes in output to cryptic identifiers, except if wrapped in a :global(...) pseudo class)
{ loader: "sass-loader" }, // to convert SASS to CSS
// NOTE: The first build after adding/removing/renaming CSS classes fails, since the newly generated .d.ts typescript module is picked up only later
Also put a declarations.d.ts
in your project:
// We need to tell TypeScript that when we write "import styles from './styles.scss' we mean to load a module (to look for a './styles.scss.d.ts').
declare module '*.scss';
And you will need all these in your package.json
's dev-dependencies:
"devDependencies": {
"@types/node-sass": "^4.11.0",
"node-sass": "^4.12.0",
"css-loader": "^1.0.0",
"css-modules-typescript-loader": "^2.0.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.3",
"typescript": "^3.4.4",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.0"
Then you should get a mystyle.d.ts
next to your mystyle.scss
containing the CSS classes you defined, which you can import as a Typescript module and use like this:
import * as styles from './mystyles.scss';
const foo = <div className={styles.myClass}>FOO</div>;
The CSS will automatically be loaded (injected as a style
element into the DOM) and contain cryptic identifiers instead of your CSS classes in the .scss, to isolate your styles in the page (unless you use :global(.a-global-class) { ... }
).
Note that the first compile will fail whenever you add CSS classes or remove them or rename them, since the imported mystyles.d.ts is the old version and not the new version just generated during compilation. Just compile again.
Enjoy.
–
–
–
declare module "*.module.css";
and remember to declare your css files with 'module'. for example
styles.module.css
importing:
import React from 'react';
import styles from './styles.module.css';
–
As @Kalle mentions
TypeScript does not know that there are files other than .ts or .tsx so
it will throw an error if an import has an unknown file suffix.
To avoid TS showing this error, my approach is to create a types folder and inside add an .d.ts
extension file containing the declarations.
Like so:
About .d.ts
files
TypeScript has two main kinds of files. .ts
files are implementation
files that contain types and executable code. These are the files that
produce .js
outputs, and are where you’d normally write your code.
.d.ts
files are declaration files that contain only type information.
These files don’t produce .js
outputs; they are only used for
typechecking.
You can read more about TS declarations here
I'm using typescript-plugin-css-modules
npm install -D typescript-plugin-css-modules
tsconfig.json
"compilerOptions": {
"plugins": [{ "name": "typescript-plugin-css-modules" }]
Remember to declare your css files with .module.css
.
Importing:
import styles from './styles.module.css'
If using Sass, replace the .css
statements with .scss
.
This works for me (I am using Typescript + vite).
Adding this to declaration.d.ts
file in project root folder
declare module "*.module.css";
declare module "*.module.scss";
Adding "declaration.d.ts" to "include" in tsconfig.json
.
"compilerOptions": {...},
"include": ["src", "declaration.d.ts"],
This will allow the declaration to work in the src
folder too not just the root
folder which declarations.d.ts
is located.
You can add declaration.d.ts
in directly in the folder that you import styles directly but it's a bad bad idea.
100% works
Just put a "declarations.d.ts" in your project and add the following line to it:
declare module '*.css';
Heads Up If You Are Using tsconfig.json Path Setting
Note that if you are using these solutions in conjunction with tsconfig paths to shorten your import you will need additional configuration.
If you happen to use a path tsconfig like such:
"compilerOptions": {
"paths": {
"style/*": [ "src/style/*" ],
So you can do:
import { header } from 'style/ui.scss';
Then you need to also add a modules resolve configuration on your webpack like such:
module.exports = {
resolve: {
alias: {
style: path.resolve(__dirname, 'src', 'style')
Make sure the path is set according to your setup.
This makes it so webpack knows where to look since it thinks the new import path is actually a module so it defaults to node_modules directory. With this configuration, it knows where to look and finds it and the build works.
As per the answer @Kalle delivered, I also found that I needed to make the declaration typings discoverable within the include
tsconfig option:
"include": ["./src/**/*.tsx", "./src/**/*.ts", "./typings/*.ts"]
With the typings
containing the declaration.d.ts
file seen in @Kalle's answer.
–
The above answers did'nt work for me and i was working on scss + TS + React ( if you are too, this answer is for you ). What i did was:
make a declarations.d.ts file in src folder and added following code in it
declare module "*.scss" {
const content: { [className: string]: string };
export = content;
then made a tsconfig.json file in src folder and added following code
"compilerOptions": {
"plugins": [{ "name": "typescript-plugin-css-modules" }]
//add the following
"include": ["src/**/*.ts", "declarations.d.ts"]
then finally installed plugin as
npm i typescript-plugin-css-modules
AND IT WORKED :)
I found the answer (at least for me).
Many answers here and there said:
// declaration.d.ts
declare module '*.scss';
Oh yeah, I did it in my existing .d.ts file:
// this.name.is.at.your.disposal.d.ts
export type {};
declare module "*.css";
declare global {
declare const NEXT_PUBLIC_SOME_URL: string;
But ts compiler still complained "Oh, I don't understand this blablabla"
And I noticed this line
export type {};
was the evil that you need to erase in whatever your god's name.
I gotta go buy a beer now.
In my project, in the /src folder, there was a react-app-env.d.ts file with the contents
/// <reference types="react-scripts" />
I couldn't figure out why he was? I looked through the search where it is imported, but the search showed 0 results.And somehow I deleted it, after that I got a lot of errors:
Cannot find module './Home.scss' or its corresponding type
declarations. TS2307 Compiled with warnings.
Cannot find module './BlockPosts.module.css' or its corresponding type
declarations. TS2307 Compiled with warnings.
Then I restored this file and all the errors disappeared
Create a file in your project in the /src folder react-app-env.d.ts write it down
/// <reference types="react-scripts" />
And maybe you will stop making mistakes too
Just add file react-app-env.d.ts
in your src direcory and write there /// <reference types="react-scripts" />
This will solve the problem by impoting various names declared in node_modules/react-scripts/lib/react-app.d.ts
–
typings.d.ts
was correctly configured
tsconfig.json
was correctly configured
webpack config was correctly configured
same setup was working on a different project
And still I was getting this error.
What helped, was to REMOVE AN IMPORT from typings.d.ts
- import { Theme } from '@mui/material/styles'
It was giving no error or warning at all. However prevented my declared modules to work properly.
Hope it helps!
–
In my case, I had upgraded the (major) version of NodeJS, which likely caused the problem. On the front end, I also saw an error
to the effect that:
Node Sass couldn't find a binding for your current environment
The solution in my case was:
npm cache clean --force
Delete the node_modules
folder for the project
Delete the package-lock.json
file
npm install
After this, running npm run dev
resulted in the message:
Failed to load C:\path\tsconfig.json: Missing baseUrl in compilerOptions
So the final step to resolve was:
Edit the tsconfig.json
file and add "baseURL": ".",
, under "compilerOptions":
, like this:
"compilerOptions": {
"baseUrl": ".",
etc etc etc
Problem was resolved at this point.
Reference:
Node Sass couldn't find a binding for your current environment
The declare module "*.module.css"; did not affected the result.
REMEMBER: Always run
npm start
to test these configuration changes to see if something happens**.
Doing this would save me this afternoon.
In my React app, created with CRA, I had to add in react-app-env.d.ts:
declare module '*.css';
Adding this declaration in declarations.d.ts, like suggested above, did not work.
For people using typescript-plugin-css-modules package. In that case you have to add in the tsconfig.json file:
"extends": "../tsconfig.json",
"plugins": [
"name": "typescript-plugin-css-modules"
The problem for me was that just one property
in the interface
of myFile.scss.d.ts
was not been generated, so I was getting error.
The cause was that a specific class existed on my myFile.scss
and was been used on my Component but, It has any CSS property on it!
.base {
&__rule1 {
// .base__rule1 was not been generated on my .d.ts file because it has any css property
&__another {
width: 120px;
margin: 0 auto 8px;
The possible solutions are:
a) Remove base__rule1
from your markup, <div classes={style.base__rule1}>
to <div>
b) Add some css property to that class
&__rule1 {
width: inherit;
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.