question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Babel macros do not works with TS "import type" before the macro import

See original GitHub issue

Describe the bug

When using import type { … } from "@lingui/react" before import { Trans } from "@lingui/macro" the macro does not use an import for Trans. This results in an obscure Uncaught ReferenceError: Trans is not defined error.

Note: I can reproduce this with Lingui 2, not with Lingui 3, but I think this should be fixed as the error message is not explicit at all and finding out what is happening is painful.

To Reproduce Steps to reproduce the behavior, possibly with minimal code sample, e.g:

import * as React from "react"

import type { withI18nProps } from "@lingui/react"
import { Trans } from "@lingui/macro"

export const Comp = () => <Trans>Foo</Trans>

This gets transpiled by Babel to:

"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Comp = void 0;

var React = _interopRequireWildcard(require("react"));

var Comp = function Comp() {
  return /*#__PURE__*/React.createElement(Trans, {
    id: "Foo"
  });
};

exports.Comp = Comp;

Note that it is using Trans and not importing @lingui/react at all.

If you comment the import type line it works as expected.

If you have a standard @lingui/react import before the import type, it works fine. If you add it after, it fails the same way as above.

I think the macro wrongly detects the import type as a normal import, and tries to add the needed export (here Trans) to the import list, which is then removed from the final output by Babel as this is TS specific and needs to be trimmed from the final output.

Additional context Add any other context about the problem here.

  • jsLingui version lingui --version: 2.9.2
  • Babel version npm list @babel/core: 7.12.3
  • Your Babel config (e.g. .babelrc) or framework you use (Create React App, Meteor, etc.)
{
  "presets": [
    "@babel/preset-typescript",
    "@babel/preset-react",
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ],
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "ssr": false,
        "transpileTemplateLiterals": true,
        "minify": true,
        "displayName": false
      }
    ],
    "lodash",
    "macros",
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-proposal-class-properties",
    [
      "@babel/plugin-transform-runtime",
      {
        "regenerator": false
      }
    ]
  ]
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
semoalcommented, Oct 27, 2020

The summary is, @lingui/macro changes his import to @lingui/react, but babel has like an issue with that, so if we use import type above of the macro will remove that import type from bundle, but the modification from @lingui/macro to @lingui/react is not done yet, when it’s executed it thinks that the import was present and tries to do something like this:

const reactImport = j.importDeclaration(linguiReactImport)
reactImports.push(Trans)

But reactImport doesn’t exist cuz “someone” removed that, that’s why the import disappears, this has tree ways of being fixed:

  • Don’t use import type
  • Move the import type after macro import
  • Search where’s this code and be sure that when running macro modification is searching other time on the AST the @lingui/react iumport and if no exists, create that.

That’s my theory, i’ve built a playground to test and the results endorse my theory

First test:

import * as React from "react"

import type { withI18nProps } from "@lingui/react"
import { Trans } from "@lingui/macro"

export const Comp = (): withI18nProps => {
  return (
      <Trans>
        Foo
      </Trans>
  )
}

Result:

"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Comp = void 0;

var React = _interopRequireWildcard(require("react"));

var Comp = function Comp() {
  return /*#__PURE__*/React.createElement(Trans, {
    id: "Foo"
  });
};

exports.Comp = Comp;

Removing import type and import the type from the normal import

import * as React from "react"

import { withI18nProps  } from "@lingui/react"
import { Trans } from "@lingui/macro"

export const Comp = (): withI18nProps => {
  return (
    <Trans>
      Foo
    </Trans>
  )
}

Result:

"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Comp = void 0;

var React = _interopRequireWildcard(require("react"));

var _react2 = require("@lingui/react");

var Comp = function Comp() {
  return /*#__PURE__*/React.createElement(_react2.Trans, {
    id: "Foo"
  });
};

exports.Comp = Comp;

As you can see require(“@lingui/react”, doesnt disappers, and trans is imported from there

Possible solution

On the lingui AST parser where’s changing macro to react, probably could be the solution, i’ll take a look asap

0reactions
tricoder42commented, Oct 27, 2020

@semoal Nice work 🥇

Read more comments on GitHub >

github_iconTop Results From Across the Web

Babel Macros - Jake Runzer
Babel Macros. Babel macros are a way to apply code transformations without having to install a new plugin for each transformation.
Read more >
Tooling - styled-components
If your scaffold is set up with babel-plugin-macros, then simply use the new styled-components/macro import instead of styled-components: import styled ...
Read more >
babel/plugin-transform-typescript
Replace the function used when compiling JSX fragment expressions. This is so that we know that the import is not a type import,...
Read more >
babel-plugin-macros - npm
Start using babel-plugin-macros in your project by running `npm i ... import macro from 'non-pure.macro'; -// Do some changes of your code ...
Read more >
Untitled
DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE ... you can import/require the preval macro at `babel-plugin-preval/macro`.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found