Globhy
AllBusinessHealthMarketingTechnologyTravelUncategorized
HAHartanto57 minutes ago2 views

Share:

How to Fix "Cannot Find Module or Type Declarations for Side-Effect Import" in TypeScript

Technology

Learn how to fix the TypeScript TS2882 error for CSS imports, understand noUncheckedSideEffectImports, and use declare module '*.css' in Next.js.

How to Fix "Cannot Find Module or Type Declarations for Side-Effect Import" in TypeScript

If you're using TypeScript with Next.js or React and see an error like:

javascript
Cannot find module 'mapbox-gl/dist/mapbox-gl.css'
or its corresponding type declarations. (TS2882)

when importing a CSS file:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

you're likely running into TypeScript's handling of side-effect imports and the noUncheckedSideEffectImports option.

The confusing part is that the application may still work correctly. Next.js can find the CSS file, the browser loads the stylesheet, and the application builds successfully in some configurations—yet TypeScript or your IDE reports an error.

Fortunately, the fix is usually straightforward.

In this guide, you'll learn:

  • What a side-effect import is in TypeScript
  • Why TypeScript reports this CSS import error
  • What noUncheckedSideEffectImports does
  • How to fix TS2882 with declare module '*.css'
  • How to configure global.d.ts
  • The difference between wildcard and exact CSS module declarations
  • Which approach is best for Next.js and React projects

What Causes the "Cannot Find Module or Type Declarations" Error?

Consider this common CSS import:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

TypeScript may report:

javascript
Cannot find module 'mapbox-gl/dist/mapbox-gl.css'
or its corresponding type declarations.

This doesn't necessarily mean that the CSS file doesn't exist.

In fact, if you've installed mapbox-gl, the file is normally located inside your node_modules directory:

javascript
node_modules/
└── mapbox-gl/
├── dist/
│ ├── mapbox-gl.js
│ └── mapbox-gl.css
└── package.json

The problem is that TypeScript needs to understand the imported module, while CSS files don't contain TypeScript type declarations.

This becomes particularly noticeable when noUncheckedSideEffectImports is enabled.

What Is a Side-Effect Import in TypeScript?

A side-effect import is an import statement that doesn't import a specific value.

For example:

javascript
import './styles.css'

There is no variable being imported:

javascript
import styles from './styles.css'

Instead, the purpose is simply to load the stylesheet.

The same applies to third-party CSS:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

The CSS is imported for its side effect—loading and applying the stylesheet.

This pattern is extremely common in React, Next.js, Vite, and other frontend applications.

Why Does TypeScript Check Side-Effect Imports?

Historically, TypeScript was relatively permissive with side-effect imports.

For example:

javascript
import './non-existent-file.css'

could sometimes go unnoticed by TypeScript.

This wasn't always desirable because a typo in an asset path could silently make it into the codebase.

noUncheckedSideEffectImports in TypeScript 5.6

TypeScript 5.6 introduced the noUncheckedSideEffectImports compiler option to make this behavior stricter.

When enabled, TypeScript checks whether side-effect imports can be resolved.

This means an import such as:

javascript
import './styles.css'

must be resolvable from TypeScript's perspective.

If TypeScript cannot find the module or an appropriate declaration, you may see:

javascript
Cannot find module './styles.css'
or its corresponding type declarations.

The option is useful because it can catch genuine mistakes, but it also means TypeScript needs additional information for non-TypeScript assets such as CSS.

Why Doesn't @types/mapbox-gl Fix the Error?

You might think installing the Mapbox TypeScript definitions should solve the problem:

javascript
npm install -D @types/mapbox-gl

But these type definitions describe the JavaScript API of Mapbox GL, not every asset distributed with the package.

For example, TypeScript can understand Mapbox's JavaScript API:

javascript
import mapboxgl from 'mapbox-gl'

but that doesn't automatically tell TypeScript what to do with:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

The CSS file is a static asset, not a TypeScript module containing type declarations.

Therefore, you need to tell TypeScript how to handle CSS imports.

How to Fix TypeScript CSS Import Errors

The most common solution is to create an ambient module declaration for CSS files.

Create a file called:

javascript
global.d.ts

Then add:

javascript
declare module '*.css' {}

That's usually all you need.

This tells TypeScript:

Any module whose filename ends with .css should be considered a valid module.

After adding the declaration, an import such as:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

will no longer produce the TypeScript error.

What Is declare module '*.css'?

The following declaration:

javascript
declare module '*.css' {}

is an ambient module declaration.

It doesn't load CSS, process CSS, or generate any JavaScript.

Instead, it provides information to the TypeScript compiler about modules that exist outside the normal TypeScript module system.

In simple terms, you're telling TypeScript:

"My build system knows how to handle CSS files. Treat CSS imports as valid modules."

The actual CSS processing is still handled by your framework and bundler.

For example, in a Next.js application, Next.js handles the CSS during the build process.

Where Should global.d.ts Go?

A simple project structure might look like this:

javascript
my-next-app/
├── app/
├── components/
├── public/
├── global.d.ts
├── package.json
└── tsconfig.json

You can also place declaration files inside a dedicated directory, depending on your project's structure.

The important part is that TypeScript must include the declaration file in the project.

For example:

javascript
{
"include": [
"global.d.ts",
"src/**/*.ts",
"src/**/*.tsx"
]
}

Your existing tsconfig.json may already include the relevant files, so don't blindly replace your configuration.

Check the include section and make sure your declaration file is covered.

Restart the TypeScript Server

If the error remains after creating global.d.ts, your editor may still be using an old TypeScript language-server state.

In VS Code, open the Command Palette:

javascript
Cmd + Shift + P

Then run:

javascript
TypeScript: Restart TS Server

You can also restart your development server if necessary.

After that, the CSS import should be recognized.

Wildcard CSS Declaration vs. Exact Module Declaration

There are two ways you can declare CSS modules.

Option 1: Wildcard Declaration

The most common approach is:

javascript
declare module '*.css' {}

This covers all CSS modules.

For example:

javascript
import './styles.css'
import './components.css'
import 'mapbox-gl/dist/mapbox-gl.css'
import 'some-library/dist/styles.css'

Option 2: Exact Module Declaration

You can also declare specific CSS files:

javascript
declare module 'mapbox-gl/dist/mapbox-gl.css' {}
declare module 'react-quill-new/dist/quill.snow.css' {}

This approach is more restrictive.

Only the explicitly declared modules are covered.

Is declare module '*.css' Safe?

A common concern is that:

javascript
declare module '*.css' {}

could cause TypeScript to accept a CSS file that doesn't actually exist.

That's true.

For example:

javascript
import 'mapbox-gl/dist/fake-file.css'

could satisfy TypeScript's module declaration because it matches:

javascript
*.css

However, this does not mean the nonexistent file will work at runtime.

Your bundler still needs to resolve the actual file.

If the file doesn't exist, the application build can still fail with a module resolution error.

This means there are two different responsibilities:

Tool

Responsibility

TypeScript

Type checking and module declarations

Next.js / bundler

Resolving and processing the actual CSS file

The wildcard declaration tells TypeScript that CSS imports are valid.

It does not disable the bundler's file resolution.

Why the Wildcard Declaration Is Usually the Best Choice

For most React and Next.js applications, this is the most practical solution:

javascript
declare module '*.css' {}

There are several reasons.

1. Less Configuration

You don't have to register every CSS file manually.

Without a wildcard declaration, you might end up with:

javascript
declare module 'mapbox-gl/dist/mapbox-gl.css' {}
declare module 'react-quill-new/dist/quill.snow.css' {}
declare module 'some-datepicker/styles.css' {}
declare module 'some-editor/dist/editor.css' {}

As your application grows, this becomes difficult to maintain.

With:

javascript
declare module '*.css' {}

new CSS imports don't require additional TypeScript declarations.

2. It Works Well With Frontend Asset Imports

CSS isn't the only type of static asset commonly imported into frontend applications.

Depending on your framework and configuration, you may also encounter declarations such as:

javascript
declare module '*.png' {}
declare module '*.jpg' {}
declare module '*.svg' {}

Using a wildcard for CSS follows the same general approach.

3. Your Bundler Still Provides Runtime Validation

The wildcard declaration doesn't make invalid imports work.

For example:

javascript
import 'mapbox-gl/dist/does-not-exist.css'

may pass TypeScript's declaration check.

But the bundler still needs to resolve the actual file.

If it cannot, the build will fail.

This gives you a useful separation:

TypeScript validates the type system.

The bundler validates the actual asset.

When Should You Use an Exact CSS Declaration?

An exact declaration can make sense if you want TypeScript to be more restrictive.

For example:

javascript
declare module 'mapbox-gl/dist/mapbox-gl.css' {}

This explicitly documents the CSS dependency your application expects.

It's useful when:

  • You have only a few CSS imports.
  • You want stricter module declarations.
  • You want TypeScript to catch more invalid CSS paths.
  • You are maintaining a library with carefully controlled imports.

For a typical Next.js application with multiple third-party packages, however, the wildcard approach is generally more convenient.

Recommended Configuration for Next.js

If you're using Next.js and encounter:

javascript
TS2882: Cannot find module or type declarations for side-effect import

and the problematic import is a CSS file, start with:

global.d.ts

javascript
declare module '*.css' {}

Then make sure the file is included in your TypeScript project.

For example:

tsconfig.json

javascript
{
"include": [
"global.d.ts",
"src/**/*.ts",
"src/**/*.tsx"
]
}

Then restart the TypeScript server.

Your original import can remain unchanged:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

You don't need to move the CSS file into your own src directory.

Frequently Asked Questions

Why does TypeScript say it cannot find a CSS file that exists?

Because TypeScript needs to resolve the import through its module/type system. The fact that the CSS file exists on disk doesn't automatically provide TypeScript with a module declaration for it.

Adding:

javascript
declare module '*.css' {}

tells TypeScript how to treat CSS modules.

Do I need @types/mapbox-gl to fix this error?

Not for the CSS declaration itself.

@types/mapbox-gl provides TypeScript definitions for the Mapbox JavaScript API. It does not necessarily declare Mapbox's distributed CSS files.

Does declare module '*.css' import the CSS?

No.

It only provides a declaration for TypeScript. Your framework or bundler is still responsible for loading and processing the CSS.

Will declare module '*.css' hide typos?

It can prevent TypeScript from detecting some invalid CSS paths because any .css module matches the wildcard.

However, the bundler still has to resolve the actual file during development or production builds.

Should I use declare module '*.css' in Next.js?

For most Next.js applications that import CSS assets from dependencies, it's a practical solution when TypeScript reports unresolved CSS side-effect imports.

What is TS2882?

TS2882 is the TypeScript diagnostic associated with an unresolved side-effect import when TypeScript's stricter side-effect import checking is enabled.

Conclusion

The error:

javascript
Cannot find module or type declarations for side-effect import

doesn't necessarily mean your CSS file is missing.

When importing a stylesheet such as:

javascript
import 'mapbox-gl/dist/mapbox-gl.css'

TypeScript may complain because it doesn't have a declaration describing CSS modules.

This can become more visible when noUncheckedSideEffectImports is enabled.

For most Next.js and React applications, the simplest solution is to create a global declaration:

javascript
// global.d.ts
declare module '*.css' {}

Then make sure global.d.ts is included in your tsconfig.json and restart the TypeScript server.

The key idea is:

TypeScript needs a declaration for the CSS module, while your bundler is responsible for resolving and processing the actual CSS file.

Once you understand that distinction, errors involving CSS, fonts, images, and other static assets become much easier to troubleshoot.

Share:

More in Technology

View category