269

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>
        </div>

    );
  }
}

export default App;

What else is required to enable typesafe stylesheet module importing?

1
  • 1
    I had this error in VSCode, restarting VSCode fixed it. Commented Apr 27, 2024 at 11:58

27 Answers 27

313

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-loadercss-loaderstyle-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;
}
Sign up to request clarification or add additional context in comments.

7 Comments

Hey this did not work for me, has something recently changed. stackoverflow.com/questions/56563243/…
FYI for anyone who this might help. For me, I had to put the declaration.d.ts file in the project root. Putting it in a subfolder with a path under "types" in the tsconfig file did not work for me.
I was using the typescript-plugin-css-modules plugin, was getting the error still on build, and this resolved it for me.
Please include declaration.d.ts into tsconfig.json file as{ "include": ["./declaration.d.ts"] }
@Etheryte yes you are right including the undefined type is closer to reality, but that's also something with a strong impact on the developer experience and where you have to choose your compromise.
|
112

Just add the file typings.d.ts containing:

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';

4 Comments

Adding only typings.d.ts file worked
The typings.d.ts needs to go somewhere in your src folder or below. Also don't forget to add declare module "*.module.scss"; if you use SASS
Thanks, this worked perfectly for me in a project that already had webpack configured with sass-loader etc.
This partially works but also the compiler doesnt complain anymore if a file doesnt exist!
95

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.

4 Comments

"NOTE: The first build after adding/removing/renaming CSS classes fails, since the newly generated .d.ts typescript module is picked up only later" -- How to solve that part?
@JonLauridsen it can be solved by setting ts-loader at the bottom (end) of array of the rules in webpack.config.js. So ts-loader will pickup a correct *.scss.d.ts files every compilation cause they will be generated before.
@YanPak Thanks, adding a global.d.ts to my src directory along with moving the ts-loader to below the style loaders fixed it for me.
This partially works but also the compiler doesnt complain anymore if a file doesnt exist!
90

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:

enter image description here

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

3 Comments

Confirmed that the 'types' folder is actually needed
Worked with *.module.scss" as well.
This is the most comprehensive answer as it clearly points out the solution.
36

I'm using typescript-plugin-css-modules

npm install -D typescript-plugin-css-modules

tsconfig.json

{
  "compilerOptions": {
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  }
}

1 Comment

in vs code add this to settings.json "typescript.tsserver.pluginPaths": [ "typescript-plugin-css-modules" ],
32

This works for me (I am using Typescript + vite).

  1. Adding this to declaration.d.ts file in project root folder

    declare module "*.module.css";
    declare module "*.module.scss";
    
  2. 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.

2 Comments

You don't technically need to do any of this for Vite to work I think. It's just my IDE (Visual Studio 2019)'s TS analyzer that grumbles. This does, however, silence the VS error. In addition to this, a) I added a declaration body so the import gets recognized as a string when imported with import style from './file.scss?inline'. This looks like declare module "*.scss?inline" { const x: string; export default x; }. b) you don't need to modify your tsconfig's include if your .d.ts file is in a child directory.
@GeneralGrievance strangely, I am experiencing the opposite. VSCode doesn't complain, pnpm dev works fine, but it starts yelling about not finding css modules on trying to build. I am also using Vite + react + TS setup and scratching my head on how to get rid of this error TS2307 and get the build to finish. Do you think putting the declaration files in a subdirectory, say, "types" as suggested in an answer above is a better solution?
18

Just add the declaration.d.ts file containing:

declare module "*.module.css";

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.

Comments

16

Just put a "declarations.d.ts" in your project and add the following line to it:

declare module '*.css';

1 Comment

It is not working for me.
14

The above answers didn't work for me, and I was working on scss + TS + React. 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": {
     // In anticipation of installing the plugin
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  },
  // Include source directories and declarations
  "include": ["src/**/*.ts", "declarations.d.ts"]
}

Then finally installed plugin as

npm i typescript-plugin-css-modules

and it worked!

1 Comment

Thank you, this allows me to sync scss variables into a JS based theme framework.
9

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.

Comments

8

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.

1 Comment

This was the only additional configuration I needed except for adding a declaration.d.ts file. Thanks!
4

Late to the party, but in case it helps someone else, I ran into a similar issue in a React + TypeScript app:

src/main.tsx:4:8 - error TS2307: Cannot find module './index.css' or its corresponding type declarations.

4 import "./index.css";
         ~~~~~~~~~~~~~

As other already mentionned in the thread, the issue was due to missing type definitions. Since the app is Vite based, the fix was to add a src/vite-env.d.ts file with the following content:

/// <reference types="vite/client" />

This resolved the problem.

2 Comments

This fixed it for me, but I also needed to modify my tsconfig.json file to include the vite-env.d.ts file like this: "include": [ "src", "vite-env.d.ts"]
Since "src" is already included in the tsconfig.json file like "include": [ "src"] so I did not have to add the vite-env.d.ts file explicitly to it.
2

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

2 Comments

I don't believe this answers the general question about resolving errors parsing imports of css/scss modules.
This helped me fix the exact same problem. I copied over files from an existing react-scripts projects and I forgot about this file. When adding this file the error went away.
2

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.

Comments

2

I had this exact problem, however

  • 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!

2 Comments

omg, thank you so much, got stuck on this for a while now - as you suggested, removing the import (or moving to separate d.ts file helped.
Upvoting for awareness. I had the same problem. After adding an imports (i18next in my case) the scss module stuff stopped working. Thanks for sharing!
2

I'm using NextJS, CSS modules and TS, the following solutions worked for me:

  • Create a declaration.d.ts file in the root of your project ( right next to where your tsconfig.json file is). And add the following lines:

      declare module '*.css' {
      const content: Record<string, string>;
      export default content;
    }
    
  • Edit your tsconfig.json file to include the following:

    "include": [.......... "typings", "src"],
    

Comments

2

Please note that all the answers above tell to add declare module '*.module.scss' or declare module '*.module.css' assume all the style files you are creating have the extension .module.scss or .module.css, eg - styles.module.css

If you want it work for a file type xyz.scss or abc.css use declare module '*.scss or '*.css'

also restart the server

Comments

1

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

Comments

1

Maybe just restarting the TS server can work.

Using VsCode:

Windows:

type: ctrl + Shift + P or ctrl + Shift + F5

choose: > TypeScript: Restart TS server

Macbook:

type: ⇧ + ⌘ + P or F1

choose: > TypeScript: Restart TS server

Maybe it's just a file error, check if you accidentally changed a file from .ts to .tsx or .tsx to .ts

Comments

1

I had the same problem in react with vite and solved as bellow: i had a problem that index.css in main.ts can not be found while it was exist in src folder. I solved as bellow:

npm install --save-dev @types/react

create declaration.d.ts in src: src/declaration.d.ts

declare module "*.css" {
  const content: { [className: string]: string };
  export default content;
}

and in tsconfig.app.json add this "declaration.d.ts"

"include": ["src", "declaration.d.ts"]

then run npm run dev. If build your project, the error ill be removed.

Comments

0

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:

  1. npm cache clean --force

  2. Delete the node_modules folder for the project

  3. Delete the package-lock.json file

  4. 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:

  1. 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

Comments

0

In my case I solved it just commenting the loaders scss and sass:

{
                test: /\.css$/,
                use:
                    [
                        {
                            loader: 'style-loader'
                        },
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 1,
                                modules: true
                            }
                        }
                        // ,
                        // {
                        //     loader: 'sass-loader'
                        // }
                        // ,
                        // {
                        //     loader: 'scss-loader'
                        // }
                    ]
            }

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.

Comments

0

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.

Comments

0

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"
      }
    ]
}

Comments

0

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;
....
}

Comments

0

I have define the correct module declaration, and include it in my tsconfig.json, but I still got the same problem.

finally, I solved this problem by exclude large folders with source files that I do not work on. hope it will help.

"exclude": ["node_modules", "dist", ".yalc", "build", "public", "scripts"]

Comments

-3

I had the same problem in angular, I tried to run npm audit fix and it solved my problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.