Babel types transform - adds space around operators. How to bypass?

163 views Asked by At

I have a line of code I am trying to make with a babel transform.

This, const [firstName, setFirstName] = useState<string>("")

However, when I run my transform to insert this code, the <brackets> are both given extra space around them. So I get useState < string > ("")...

I feel like this is probably intentional code formatting. But for this particular area, I would like it to not do that. I don't want the extra space around the operators just for this part of my code.. How can I make that to happen?

Here's my transform/configuration

types.variableDeclaration("const", [
        types.variableDeclarator(
            types.arrayPattern([
                types.identifier("firstName"),
                types.identifier("setFirstName")
            ]),
            types.binaryExpression(
                ">",
                types.binaryExpression(
                    "<",
                    types.identifier("useState"),
                    types.identifier("string")
                ),
                types.parenthesizedExpression(types.stringLiteral(""))
            )
        )
    ]
)

"@babel/core": "^7.12.13",

"@babel/plugin-syntax-typescript": "^7.12.13",

I could only find information on how to add the extra spacing, but not remove it.

1

There are 1 answers

5
loganfsmyth On BEST ANSWER

If you're trying to make a type annotation, you need to make a type annotation AST node, not a binaryExpression and parenthesizedExpression and such. AST nodes have specific meanings and what you are constructing is a syntactic description rather than a semantic description, hence the weirdness.

If you don't know the AST node types that you need, it is generally a good idea to run Babel's parser on the code you want to produce, because they you can see the node types that you need.

In your case you need something like this:

const callNode = types.callExpression(
  types.identifier("useState"),
  [types.stringLiteral("")]
);
callNode.typeParameters = types.tsTypeParameterInstantiation([
  types.tsStringKeyword()
]);

const declNode = types.variableDeclaration("const", [
  types.variableDeclarator(
    types.arrayPattern([
        types.identifier("firstName"),
        types.identifier("setFirstName")
    ]),
    callNode,
  )
]);

All that said, constructing all of this by hand can be pretty tough, so depending on your needs, I'd consider doing it with template, e.g.

const declNode = template.statement({ plugins: ["typescript"] }).ast`
  const [firstName, setFirstName] = useState<string>();
`;