How to write a type declaration for a CSS Module as ES Module

Viewed 1465

I am upgrading Gatsby from v2 to v3, and in this update CSS Modules are imported as ES Modules.

The web moves forward and so do we. ES Modules allow us to better tree shake and generate smaller files. From now on you’ll need to import CSS modules as: import { box } from './mystyles.module.css'

The old approach will no longer compile.

After changing the imports, it compiles correctly and looks as expected. The only problem is, that I am getting type errors as the exports cannot be found.

My assumption is, that the type declaration is wrong, but I am not sure how to dynamically type this without naming each possible CSS class as an export.

I have also tried import * as styles, which first of all is discouraged (as it prevents tree-shaking), but also cause type errors.

Foo.module.css:

.foo { color: red; }
.bar { color: blue; } 

Foo.tsx:

import { foo, bar } from "./Foo.module.css"
// Module "*.module.css" has no exported member 'foo'
// Module "*.module.css" has no exported member 'bar'

css.d.ts:

declare module "*.module.css" {
    const styles: { [className: string]: string }
    export * from styles
}
2 Answers

I was hitting the same issue, and the following appears to work for me:

declare module "*.module.css" {
    const styles: { [className: string]: string }
    export = styles
}

This may, however, be an abuse of TypeScript, since according to the TypeScript documentation, the export = syntax is supposed to be for CommonJS and AMD modules, where it represents the exports in those module systems.

I think the only way is to use:

import styles from "./Foo.module.css";

Unless you are able to export individual styles from the css file in your d.ts:

declare module '*.css' {
  const styles: {
    [className: string]: string;
    foo: string;
    bar: string;
  };
  export default styles; 
}

btw the syntax in your types declaration was incorrect, if you use from in your export statement then it expects a string (path or npm package name).

Related