'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 1:[1]

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

Solution 2:[2]

You could try to cast the variable explicitly: styles[`icon-${alignIcon}`] as CssExports.

Alternatively, you can suppress this error by adding the following to your tsconfig.json compilerOptions:

compilerOptions: {
  "suppressImplicitAnyIndexErrors": true,
}

Solution 3:[3]

Seems like your alignIcon param is optional, so it might be null. Make sure that you handle this case by having some default value there:

export const Button = ({ alignIcon = "left", className, onClick, children }: Props, ref) => {
    /* element body */
})

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex Foxleigh
Solution 2 btk
Solution 3 chakzefir