How can I use className on SVG imported as a component in Typescript React.FC

3.8k views Asked by At

I have React, Typescript, svgr. Everything looks ok.

{
  test: /\.svg$/,
  use: ['@svgr/webpack'],
},
import Logo from 'assets/icons/logo.svg';
<Logo className={iconClassName} />;

TS doesn't like it.

TS2322: Type '{ className: string; }' is not assignable to type 'IntrinsicAttributes'.   Property 'className' does not exist on type 'IntrinsicAttributes'.

What should I do about it?

Thanks!

PS Interesting! When I import {ReactComponent as Logo} - I don't have errors anymore.

4

There are 4 answers

1
Near On

Think you cannot give className to components like that without using props. What I would suggest you to do is as follows:

import Logo from 'assets/icons/logo.svg';
<img src={Logo} className={iconClassName}/>
2
user10384449 On

Try this code:

 <div className={iconClassName}>
  <img src="assets/icons/logo.svg"/>
 </div>
0
Himanshu Patil On

I have created index.d.ts types file and have added following code

declare module "*.svg" {
  import React = require("react");
  const src: React.FC<React.SVGProps<SVGSVGElement>>;
  export default src;
}

This way you will also have access to other all props supported by svg tag

Note:- by default @svgr/webpack will try to export the React Component via default export i.e to import svg you have to import like import Star from "./assets/star.svg" and in this case above mentioned types were not working. so in webpack.config(next.config.js) i set the exportType option to named and so imports were import { ReactComponent as Star} from "./assets/star.svg" and the above typings were working.

 ....
{
      test: /\.svg$/i,
      issuer: { and: [/\.(js|ts)x?$/] },
      use: [
        {
          loader: '@svgr/webpack',
          options: { 
            exportType: 'named',
            ....
          },
        },
      ],
    }
....
0
Joshua On

You can wrap the svg component and style it as a child of the parent element, hence you could do this

import Logo from 'assets/icons/logo.svg';

<div className={iconClassName}>
  <Logo />;
</div>

Then have a stylesheet somewhere targetting the svg child

.iconClassName > :first-child {
  width: 400px;
  /* any other style you need */
}