javascriptreactjstypescriptsasstyped

TypeScript definitions files for scss module doesnt work


I just create a React project use rollup, below is my rollup config file:

rollup.config.js

import serve from "rollup-plugin-serve";
import livereload from "rollup-plugin-livereload";
import babel from "@rollup/plugin-babel";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import replace from "@rollup/plugin-replace";
import image from "@rollup/plugin-image";
import postcss from "rollup-plugin-postcss";

const isDevelopment = process.env.NODE_ENV === 'development';

const extensions = [".js", ".jsx", ".ts", ".tsx"];

export default {
  input: isDevelopment ? "src/index.tsx" : "src/index.ts",
  output: [
    {
      file: "dist/iife/bundle.js",
      format: "iife", // for local dev
      sourcemap: true,
    },
    {
      file: "dist/esm/bundle.js",
      format: "esm", // for esm
      sourcemap: true,
    },
  ],
  plugins: [
    image(),
    postcss({
      autoModules: true,
      extensions: [".css", ".scss"],
    }),
    nodeResolve({
      extensions,
    }),
    replace({
      preventAssignment: true,
      "process.env.NODE_ENV": JSON.stringify("development"),
    }),
    commonjs(),
    babel({
      babelHelpers: "bundled",
      extensions,
    }),
    serve({
      open: true,
      verbose: true,
      contentBase: ["", "public"],
      host: "localhost",
      port: 3000,
    }),
    livereload({ watch: "dist" }),
  ],
};

and I use typed-scss-modules package to generate TypeScript definition files for scss file.

styles.module.scss

.test-test {
  color: red;
} 

the generated types file like this:

styles.module.d.ts

export type Styles = {
  testTest: string;
};

export type ClassNames = keyof Styles;

declare const styles: Styles;

export default styles;

And when I use the styles in my React component, it seems that the styles.testTest is not passed to the dom correctly.

App.tsx

import styles from './styles.module.scss';

const App: React.FC = () => {
  return <div className={styles.testTest} {...restProps}>{children}</div>;
};

enter image description here

The div element receive an undefined instead of test-test class. Does anyone know the reason?


Solution

  • This library only generates TypeScript definitions, types will be erased after compiling. it will not touch the runtime code. The runtime CSS class name is still test-test. That's why you got undefined.

    Try the --nameFormat: none option, the default value is camel.

    none: do not modify the given class names

    typed-scss-modules ./styles.module.scss --nameFormat none --exportType default
    

    Output:

    export type Styles = {
        'test-test': string;
    };
    
    export type ClassNames = keyof Styles;
    
    declare const styles: Styles;
    
    export default styles;
    

    Use it like className={styles['test-test']}