Search code examples
cssreactjstypescriptsasscss-modules

TypeScript seems to be seeing a variable as 'any' even though it's defined


I have the following component:

import React from 'react';
import classNames from 'classnames';

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

const cx = classNames.bind(styles);

interface Props {
  /**
   * Allows a user to apply a custom class
   */
  className?: string;
  /**
   * The content to show in the button
   */
  children: ReactNode;
  /**
   * The if you want to include an icon, this specifies the side of the button the icon should appear on
   */
  alignIcon?: 'left' | 'right';
  /**
   * The event action to fire when the button is clicked
   */
  onClick?: (fn) => void;
}


/* Render component */
export const Button = React.forwardRef<HTMLButtonElement, Props>(
  ({ alignIcon, className, onClick, children }: Props, ref) => (
    <button
      ref={ref}
      className={cx(
        styles['button'],
        alignIcon && styles[`icon-${alignIcon}`],
        className
      )}
      onClick={onClick}
    >
      {children}
    </button>
  )
);

Button.displayName = 'Button';

export default Button;

It works exactly as I would want it to, however I get the following error when I run tsc

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'CssExports'.
  No index signature with a parameter of type 'string' was found on type 

It appears to not like the use of the variable as if I replace styles[`icon-${alignIcon}`] with styles['icon-left'] or styles['icon-right'], the error goes away. I'm unsure where the implied any is coming from.

In addition, here is the generated styles.modules.scss.d.ts file which has the CssExports in it:

interface CssExports {
  'button': string;
  'error': string;
  'icon': string;
  'icon-left': string;
  'icon-none': string;
  'icon-right': string;
}
export const cssExports: CssExports;
export default cssExports;


Solution

  • I had the issue in other components too, so I 'resolved' the issue by just adding a generic scss-modules.d.ts file to the project and removing all of the specific ones. If anyone is interested, that file looks like this:

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