Svgr: Custom template not compatible with TypeScript typings - SyntaxError Unexpected token, expected ";"

Created on 28 Nov 2019  ·  4Comments  ·  Source: gregberge/svgr

🐛 Bug Report

When running svgr -d src/svg src/svg --ext tsx --template ./src/utils/svgTemplate.ts with the following template:

function template(
  { template },
  opts,
  { imports, componentName, props, jsx, exports },
) {
  return template.ast`${imports}
const ${componentName} = (${props}): JSX.Element => {
  return (
    ${jsx}
  );
};
export default ${componentName};
`;
}

module.exports = template;

It crashes with:

yarn svg       
yarn run v1.17.3
$ npx svgr -d src/svg src/svg --ext tsx --template ./src/utils/svgTemplate.ts --no-prettier
/Users/vadorequest/dev/TFP/node_modules/@svgr/cli/lib/index.js:123
    throw error;
    ^

SyntaxError: /Users/vadorequest/dev/TFP/src/svg/AnimatedPhone.svg: Unexpected token, expected ";" (3:15)
  1 | /* @babel/template */;
  2 | $0
> 3 | const $1 = ($2): JSX.Element => {
    |               ^
  4 |   return (
  5 |     $3
  6 |   );
    at Object.raise (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:6975:17)
    at Object.unexpected (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:8368:16)
    at Object.semicolon (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:8350:40)
    at Object.parseVarStatement (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:11127:10)
    at Object.parseStatementContent (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:10723:21)
    at Object.parseStatement (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:10656:17)
    at Object.parseBlockOrModuleBlockBody (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:11232:25)
    at Object.parseBlockBody (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:11219:10)
    at Object.parseTopLevel (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:10587:10)
    at Object.parse (/Users/vadorequest/dev/TFP/node_modules/@svgr/plugin-jsx/node_modules/@babel/parser/lib/index.js:12097:10)
error Command failed with exit code 1.

The issue is related to the part : JSX.Element that is TypeScript way of specifying the return type of the function. Removing that part fixes the issue, but doesn't allow to specify which type the function will return.

This seems to be thrown by Babel, which doesn't understand it's reading TypeScript.

Expected behavior

It should use a typescript-friendly babel when targeting ts/tsx filename extension.

Run npx envinfo --system --binaries --npmPackages @svgr/core,@svgr/cli,@svgr/webpack,@svgr/rollup --markdown --clipboard

Paste the results here:

## System:
 - OS: macOS 10.15
 - CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
 - Memory: 558.28 MB / 16.00 GB
 - Shell: 5.7.1 - /bin/zsh
## Binaries:
 - Node: 10.17.0 - ~/.nvm/versions/node/v10.17.0/bin/node
 - Yarn: 1.17.3 - /usr/local/bin/yarn
 - npm: 6.11.3 - ~/.nvm/versions/node/v10.17.0/bin/npm
 - Watchman: 4.9.0 - /usr/local/bin/watchman
## npmPackages:
 - @svgr/cli: 4.3.3 => 4.3.3 

Most helpful comment

I also faced this problem but it was from prettier side.
We can see the config here (notice babel parser): https://github.com/gregberge/svgr/blob/f620bea926af961643baeaf11bf4fec05caf3b8a/packages/plugin-prettier/src/index.js#L10-L17

And we might have issues like this:

SyntaxError: Unexpected token, expected ";"
> 11 | export default forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(SvgAddValue);
     |                                        ^

So I changed the parser in the .svgrrc.js config to typescript and it works fine:

// .svgrrc.js
...
module.exports = {
  ...
  prettierConfig: {
    parser: 'typescript',
  },
};

All 4 comments

Please follow carefully this guide for TypeScript usage. You forgot template.smart({ plugins: ['typescript'] }).

Thank you! I suggest to improve the readme to make a reference to this link in order to find this information more easily in the future. :)

Here's my implementation:

/**
 * Template for React SVG
 *
 * Converts the given SVG into a TypeScript-compatible React component
 *
 * @see https://www.smooth-code.com/open-source/svgr/docs/typescript/
 * @see https://github.com/smooth-code/svgr
 */
function template(
  { template },
  opts,
  {
    imports, componentName, props, jsx, exports,
  },
) {
  const typeScriptTpl = template.smart({ plugins: ['typescript'] });

  return typeScriptTpl.ast`
import React from 'react';
import { useTheme } from 'emotion-theming';

import { Theme } from '../types/data/Theme';

const ${componentName} = (props: Props): JSX.Element => {
  const theme: Theme = useTheme();
  const { primaryColor } = theme;

  return (
    ${jsx}
  );
};

type Props = {

} & React.SVGProps<SVGSVGElement>;

export default ${componentName};
`;
}

module.exports = template;

Running it with "svg": "npx svgr -d src/svg src/svg --ext tsx --template ./src/utils/svgTemplate.ts",

I also faced this problem but it was from prettier side.
We can see the config here (notice babel parser): https://github.com/gregberge/svgr/blob/f620bea926af961643baeaf11bf4fec05caf3b8a/packages/plugin-prettier/src/index.js#L10-L17

And we might have issues like this:

SyntaxError: Unexpected token, expected ";"
> 11 | export default forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(SvgAddValue);
     |                                        ^

So I changed the parser in the .svgrrc.js config to typescript and it works fine:

// .svgrrc.js
...
module.exports = {
  ...
  prettierConfig: {
    parser: 'typescript',
  },
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

7ynk3r picture 7ynk3r  ·  4Comments

SilencerWeb picture SilencerWeb  ·  4Comments

troch picture troch  ·  5Comments

runeh picture runeh  ·  4Comments

lucasjs picture lucasjs  ·  3Comments