I'm using @svgr/webpack inside a TypeScript react project and everything works fine without doing anything fancy! But if i pass props to svg component then i face exceptions. I found many same issues here but all closed without any answer so i'm opening a new one.
Note: I'm inside a monorepo and everything works fine on ReactNative using react-native-svg-transformer with TypeScript.
<Icon /> This works fine
<Icon width={100} height={100} fill='red' /> This cause exception
Type '{ width: number; height: number; fill: string; }' is not assignable to type 'IntrinsicAttributes'.
Property 'width' does not exist on type 'IntrinsicAttributes'. TS2322
So i tried to pass typescript: true option in my .svgrrc.js file to generates .tsx files with TypeScript typings but i get following exception and even using <Icon /> without passing props wont work anymore.
SyntaxError: unknown: Unexpected token, expected "," (3:21)
1 | import * as React from "react";
2 |
> 3 | function SvgEye(props: React.SVGProps<SVGSVGElement>) {
| ^
4 | ...
I tried to use custom template to generate .tsx file but still face same problem.
// .svgrrc.js
module.exports = {
// typescript: true,
ext: 'tsx',
template: function defaultTemplate({ template }, opts, { componentName, jsx }) {
const typeScriptTpl = template.smart({ plugins: ['typescript'] })
return typeScriptTpl.ast`
import * as React from "react"
const ${componentName} = (props: React.SVGProps<SVGSVGElement>) => null;
export default ${componentName}`
},
replaceAttrValues: {
'#707070': '{props.fill}',
},
}
Im returning null instead of ${jsx} just to make error message more readable
SyntaxError: unknown: Unexpected token, expected "," (3:21)
1 | import * as React from "react";
2 |
> 3 | const SvgEye = (props: React.SVGProps<SVGSVGElement>) => null;
| ^
4 |
5 | export default SvgEye;
The typescript: true option should fix the issue.
Paste the results here:
"devDependencies": {
"@svgr/webpack": "^5.4.0",
"typescript": "^3.9.6"
}
Hey @farzinmirzaie :wave:,
Thank you for opening an issue. We'll get back to you as soon as we can.
Please, consider supporting us on Open Collective. We give a special attention to issues opened by backers.
If you use SVGR at work, you can also ask your company to sponsor us :heart:.
So I had the exact same problem but with nextjs. It seems that when I added custom.d.ts with module desciber for *.svg it seems to work properly
// custom.d.ts
declare module '*.svg' {
import * as React from 'react';
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
// next.config.js (where I inject webpack support to next webpack config)
module.exports = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
use: [
{
loader: '@svgr/webpack',
},
],
});
return config;
},
};
and now type any prop for svg component, the only downside is it doesnt propose any props in IDE, but maybe its my fault, I'm writing in typescript for about a week :)
@michalpokojski Thank you but still not working for me! I see you are no passing typescript: ture option to @svgr/webpack so you are not generating SVG components with typescript template. can you share your tsconfig.json file here?
@farzinmirzaie sure, i've deleted typescript: true just because it was not working, making same errors as yours, here's the config
{
"compilerOptions": {
"target": "es6",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"baseUrl": "."
},
"exclude": ["node_modules", ".next", "out"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js", "custom.d.ts"]
}
I even tried to include ext: 'tsx' but with same result, just like it wouldn't generate tsx files but normal js.
@michalpokojski Thank you for sharing, But i couldn't make it work!
It should not has anything to do with monorepo but i don't know what else can be the problem.
FYI if you're configuring your SVGR to work in tandem with the file loader and by default, when importing an SVG file you'll get the file's URL by default you have to import the ReactComponent export specifically to get the React component. I tweaked the suggestion from https://github.com/gregberge/svgr/issues/473#issuecomment-662681490 slightly and found this to work with this scenario:
declare module "*.svg" {
import * as React from "react";
const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
export { ReactComponent };
export default string;
}
Thought it could be useful to folks.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Hi, I was just having this problem, and this is how I got it to work: ✅
.svgrrc.js
module.exports = {
template: require('./typescript-template'),
ext: 'tsx',
prettierConfig: {
parser: 'typescript',
},
jsx: {
babelConfig: {
plugins: [
// I removed these properties to have full control over them
[
'@svgr/babel-plugin-remove-jsx-attribute',
{
elements: ['path'],
attributes: ['strokeWidth', 'stroke'],
},
],
],
},
},
}
typescript-template.js
function typescriptTemplate(
{ template },
opts,
{ imports, interfaces, componentName, props, jsx, exports },
) {
const plugins = ['jsx'];
if (opts.typescript) {
plugins.push('typescript')
}
const typeScriptTpl = template.smart({ plugins });
const formattedName = `${componentName.name}: React.FC<React.SVGProps<SVGSVGElement>>`
return typeScriptTpl.ast`
import React from 'react';
const ${formattedName} = ${props} => {
return ${jsx};
}
${exports}
`
}
module.exports = typescriptTemplate
`
CLI Command:
npx @svgr/cli --out-dir src/assets/svg/SVGComponents --template typescript-template.js --typescript
Hope it serves you well! ☺️
Most helpful comment
So I had the exact same problem but with nextjs. It seems that when I added
custom.d.tswith module desciber for*.svgit seems to work properlyand now type any prop for svg component, the only downside is it doesnt propose any props in IDE, but maybe its my fault, I'm writing in typescript for about a week :)