Best way to convert only JSX in TSX and maintaining TS

1.3k Views Asked by At

I have a bunch of TSX components written in Inferno (similar to React/Preact). I'm in need of just .ts versions with the JSX aspects converted. The environment I'm using it in only supports TypeScript and the Inferno JSX transformer is only written for Babel. I believe I can do this with Babel but not sure which flags to add.

Here's an example of my a script:


import { Component, linkEvent } from 'inferno';

import './index.scss';

interface HeaderProps {
  name: string,
  address: string
}

export default class Header extends Component {

  render(props:HeaderProps) {
    return (
      <header class="wrap">
        <img class="logo" src="logo.svg" />
        <h1>{ props.name }</h1>
        <img src="arrow.svg" />
      </header>
    );
  }
}

After I compile this script any of the TS such as the interface should remain, however the JSX should be converted into createVNode() functions. The babel plug-in to do this is: https://github.com/infernojs/babel-plugin-inferno

Here's my current .babelrc:

{
  "compact": false,
  "presets": [
    [
      "@babel/preset-env",
      {
        "loose": true,
        "targets": {
          "browsers": ["ie >= 11", "safari > 10"]
        }
      }
    ],
    [
      "@babel/typescript",
      { "isTSX": true, "allExtensions": true }
    ]
  ],
  "plugins": [
    ["babel-plugin-inferno",
    { "imports": true }],
    "@babel/plugin-transform-runtime",
    [
      "@babel/plugin-proposal-class-properties",
      { "loose": true }
    ]
  ]
}

I'm including @babel/typescript in the rc file because it needs to be able to read TS without complaining about syntax. However, the output should be retained.

If this is not the best approach, can you make a suggestion on a more effective way of converting this? ps. I can't use the TS JSX transformer, it's not compatible with Inferno.

Here's my tsconfig:

{
    "compilerOptions": {
        "pretty": true,
        "target": "es5",
        "module": "esnext",
        "allowSyntheticDefaultImports": true,
        "preserveConstEnums": true,
        "sourceMap": true,
        "moduleResolution": "node",
        "lib": ["es2017", "dom"],
        "types": [
            "inferno"
        ],
        "jsx": "preserve",
        "noUnusedLocals": true,
        "baseUrl": "./src",
        "noEmit": true,
        "skipLibCheck": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,
    },
    "include": [
        "src/**/*",
        "node_modules/inferno/dist/index.d.ts"
    ]
}
1

There are 1 best solutions below

1
On BEST ANSWER

This is the .babelrc you need:

{
  "plugins": [
    ["babel-plugin-inferno", { "imports": true }],
    ["@babel/plugin-syntax-typescript", { "isTSX": true }],
  ]
}

Note, don't use tsc, use babel only.

Unfold to see test result:

// ============== input ==============
const x: number  = 1;
enum Enum { one, two }
interface Foobar { key: string; }

const bar = () => <div>bar</div>
const zoo = () => <><span>yolo</span></>


// ============== output ==============
import { createVNode, createFragment } from "inferno";
const x: number = 1;
enum Enum {
  one,
  two,
}
interface Foobar {
  key: string;
}

const bar = () => createVNode(1, "div", null, "bar", 16);

const zoo = () => createFragment([createVNode(1, "span", null, "yolo", 16)], 4);