Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting Syntax Error when using svgr with typescript #354

Closed
arturhenryy opened this issue Nov 11, 2019 · 12 comments
Closed

Getting Syntax Error when using svgr with typescript #354

arturhenryy opened this issue Nov 11, 2019 · 12 comments

Comments

@arturhenryy
Copy link

So i set up svgr in my next.js project and i am getting this error

[ error ] ./public/static/icons/ic-car.svg
SyntaxError: unknown: Unexpected token, expected "," (3:23)

  1 | import React, { SVGProps } from 'react';
  2 |
> 3 | const SvgIcCar = (props: SVGProps<SVGSVGElement>) => <svg viewBox="0 0 64 64" {...props}><path d="M32 0C14.3 0 0 14.3 0 32s14.3 32 32 32 32-14.3 32-32S49.7 0 32 0zm0 2.9c16 0 29.1 13 29.1 29.1 0 4.5-1 8.7-2.8 12.5V31.6c0-1-.4-1.9-1.1-2.5L54 26.3l4-1.4c.8-.3 1.3-1.2.9-2l-.4-.9c-.2-.6-.8-.9-1.4-.9H51l-1.9-5.7c-.4-1.3-1.6-2.1-2.9-2.1H17.8c-1.3 0-2.5.9-2.9 2.1L13 21H6.9c-.6 0-1.2.4-1.4.9l-.4.9c-.3.8.1 1.8.9 2l4 1.4L6.8 29c-.7.6-1.1 1.6-1.1 2.5v12.9c-1.8-3.8-2.8-8-2.8-12.5C2.9 16 16 2.9 32 2.9zM15.1 24.6l2.7-8.4h28.4l2.7 8.4H32zm4.5 9.5c0 .9-.7 1.6-1.6 1.6h-7.1c-.9 0-1.6-.7-1.6-1.6v-1.5c0-1 1-1.8 2-1.6l7.1 1.5c.7.2 1.2.8 1.2 1.6zm26-1.6l7.1-1.5c1-.2 2 .6 2 1.6v1.5c0 .9-.7 1.6-1.6 1.6H46c-.9 0-1.6-.7-1.6-1.6 0-.8.5-1.4 1.2-1.6zM32 61.1c-9.9 0-18.7-5-23.9-12.6h7v-4.6h34v4.6h7C50.7 56.1 41.9 61.1 32 61.1z" /></svg>;
    |                        ^
  4 |
  5 | export default SvgIcCar;

i set up the template for typescript using the svgrrc. exactly like stated in the documentation

module.exports = {
  template({ template }, opts, { imports, componentName, props, jsx, exports }) {
    const typeScriptTpl = template.smart({ plugins: ["typescript"] });
    return typeScriptTpl.ast`
      import React, { SVGProps } from 'react';
      const ${componentName} = (props: SVGProps<SVGSVGElement>) => ${jsx};
      export default ${componentName};
    `;
  },
};

i have absolutely no clue why this happes, because i did everything like stated in the documentation.

@gregberge
Copy link
Owner

Hello @arturhenryy, I am sorry I am not able to help on TypeScript stuff :(.

@rpavlovs
Copy link

I have exactly same issues. Template doesn't seem to be working correctly. Here is my babel config:

{
      test: /\.svg$/,
      use: [
        defaultLoaders.babel,
        {
          loader: '@svgr/webpack',
          options: {
            ext: 'tsx',
            template: (
              { template },
              opts,
              { imports, componentName, props, jsx, exports }
            ) => {
              const typescriptTemplate = template.smart({
                plugins: ['typescript'],
              })
              return typescriptTemplate.ast`
                import * as React from 'react';
                const ${componentName} = (props: React.SVGProps<SVGSVGElement>) => ${jsx};
                export default ${componentName};
              `
            },
          },
        },
      ],
    }

@arturhenryy
Copy link
Author

@rpavlovs so in the end i gave up trying and went with ReactSVG which works seamless with typescript so far

@thierry-prost
Copy link

thierry-prost commented Feb 24, 2020

Here's what I tried:

I have the same issue: SyntaxError: unknown: Unexpected token, expected ","

I changed the template to
const ${componentName}: React.FC<React.SVGProps<SVGSVGElement>> = props => ${jsx};
and
ext: 'tsx',

This seems to do the trick because the "Unexpected token, expected ","" does not appear anymore. However, I'm not able to import Example from './Example.svg'. Note this is a fresh project so I didn't have anything up and running beforehand.
Which version of Typescript are you gentlemen on?
Typescript 3.8.2 here

I feel like this is getting closer to the solution

@arturhenryy
Copy link
Author

@thierry-prost it was 3.7 something back then. so my general impression is that svgr is not maintained to be used with TS for now. Even if you are finding some hack to fix the issue you might risk getting new issues with future updates, thats why i went with ReactSVG even if i think svgr is superior in an non TS env.

@thierry-prost
Copy link

thierry-prost commented Feb 25, 2020

I checked and the fix was indeed that typescript was showing a warning when compiling the 'old' template. That seems to be the issue here. Now I'm faced with a whole other problem which is a Failed to execute 'createElement' on 'Document'.

I'm trying to find out whether this is a whole separate issue or related to this bug. It seems webpack emits a static/media/Example.[c254c141].svg. The file does exist but does not seem to have been modified properly

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import * as React from 'react';

var _ref =
/*#__PURE__*/
React.createElement(Circle, {
  cx: 50,
  cy: 50,
  r: 40,
  stroke: "#000",
  strokeWidth: 3,
  fill: "red"
});

var SvgExample = function SvgExample(props) {
  return React.createElement(Svg, _extends({
    height: 100,
    width: 100
  }, props), _ref);
};

export default SvgExample;

@arturhenryy
Copy link
Author

one possible problem it that your webpack svg loader config has a problem with the generated name in that case. check this thread
https://stackoverflow.com/questions/54292667/react-storybook-svg-failed-to-execute-createelement-on-document

@vocko
Copy link

vocko commented Sep 9, 2020

Hi @gregberge I have just experienced the the same issue and I think there is a problem with the compiler. It seems it is actually using jsx compiler instead of tsx (does the plugin set the extensionproperly?)

I have used this webpack config:

use: [
    {
        loader: 'babel-loader'
    },
    {
        loader: '@svgr/webpack',
         options: {
             babel: false,
             dimensions: false,
             typescript: true,
             ext: 'tsx',
             template: (
                 { template },
                 opts,
                  { imports, componentName, props, jsx, exports }
                  ) => {
                  const typescriptTemplate = template.smart({
                        plugins: ['typescript'],
                  })
                  return typescriptTemplate.ast`
                      ${imports}
                      const ${componentName} = (props: React.FC<React.SVGProps<SVGSVGElement>>) => ${jsx};
                      ${exports}
                   `
            }
        }
    },

It produces an output as follows:

import * as React from "react";

const SvgEnvelope = (props: React.FC<React.SVGProps<SVGSVGElement>>) => 
<svg viewBox="0 0 16 16" className="envelope_svg__bi envelope_svg__bi-envelope" fill="currentColor" {...props}><path fillRule="evenodd" d="M0 4a2 2 0 012-2h12a2 2 0 012 2v8a2 2 0 01-2 2H2a2 2 0 01-2-2V4zm2-1a1 1 0 00-1 1v.217l7 4.2 7-4.2V4a1 1 0 00-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 002 13h12a1 1 0 00.966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z" /></svg>;

export default SvgEnvelope;

And yells an error:
ERROR in ./envelope.svg
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: envelope.svg: Unexpected token, expected "," (3:26)
(it complains about the colon after the props)

However, I have copied that code and created a self-standing component and the very same babel compiles just fine.

I have also removed the type definition from the props const ${componentName} = (props) => ${jsx}; and it also compiles fine, however, later my typescript checker complains about the missing type (when I have addedd a className attribute).
Type '{ className: any; }' is not assignable to type 'IntrinsicAttributes'. Property 'className' does not exist on type 'IntrinsicAttributes'.

That leads me to an impression, that the actual problem is not the template or the produced code, but the way it is further consumed by babel. It seems to be compiling in as a jsx file and not a tsx as jsx syntax seems to work fine but the compiler has a problem with any typescript related syntax.

Would be nice if someone who knows the code could look into this as it might be fairly easy to fix and would help quite a few people I guess.

@JulianKniephoff
Copy link

JulianKniephoff commented Oct 9, 2020

I got it working by specifying these

options: {
    typescript: true,
    babel: false,
    ext: "tsx",
},

for the @svgr/webpack-loader, and additionally configuring @babel/preset-typescript like so:

["@babel/typescript", {
    allExtensions: true,
    isTSX: true,
}],

What's happening here AFAIU is that Babel gets the generated code in a way that is somehow associated with the original import path, which probably ends in .svg, and thus doesn't parse it as TypeScript, because SVG is obviously not TypeScript. The settings above force babel to process every input as TypeScript (or rather TSX). This might be fine for your project, or it might not, and unfortunately I have no idea whether there is a way to control this in a more fine-grained way. :(

I also have no idea why ext: "tsx" is still necessary, but it really seems to be. 🤔

@thediveo
Copy link

thediveo commented Jan 1, 2021

I have an CRA-originating app that is unejected. Where do I put the aforementioned configuration snippets into?

@vocko
Copy link

vocko commented Jun 23, 2021

for the @svgr/webpack loader, and additionally configuring @babel/preset-typescript like so:

["@babel/typescript", {
    allExtensions: true,
    isTSX: true,
}],

Have tried the babel settings, it seems to compile the svg now (I came back to fiddle with it because I want the generated classes to be use forwardRef now), however, I'm getting compile errors in the code that was working fine without the setting :-/

@gregberge
Copy link
Owner

Fixed in #573

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants