1

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"
    ]
}
ddibiase
  • 1,412
  • 1
  • 20
  • 44
  • Are you also using tsc compiler? If you can't tell, then show us the full build config, including `tsconfig.json` – hackape Apr 22 '19 at 05:39
  • Added above. I'm assuming the first step is to change target? But to what, the options in the docs don't allow for anything but ES version? – ddibiase Apr 22 '19 at 15:01
  • OK, I finally get what you're trying to do. Sorry for earlier comment, I didn't read carefully enough. – hackape Apr 22 '19 at 16:50
  • Wow, what you want is quite perculiar. Since `.ts` is not runnable and need further transpile anyway, why is this intermediate product important to you? Might share what's the real problem you're trying to solve? Maybe we can also look into other workaround. – hackape Apr 22 '19 at 17:02
  • I know it's peculiar but Inferno's JSX transformer is special and I'm working around it for a very specific use case that's hard to give in detail. It's not a matter of solving the problem a different way unfortunately, it's specifically how the environments I'm working with operate. To clarify: I want to take a script and transform ONLY the JSX. I'd be shocked if there isn't a way. – ddibiase Apr 22 '19 at 17:16
  • Of course there's always a way, just how much time and effect you willing to pay to travel it. I'm not aware any ready made solution exists for you case. – hackape Apr 22 '19 at 17:19
  • I do have ideas through, just reluctant to try, looks quite troublesome. – hackape Apr 22 '19 at 17:21
  • I tested it out, see my answer. Actually it's easier than I thought. – hackape Apr 22 '19 at 18:41

1 Answers1

1

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);
hackape
  • 18,643
  • 2
  • 29
  • 57
  • Thanks! I was getting close to a similar conclusion. This gets me what I need to unblock the problem. Appreciate the insight. – ddibiase Apr 23 '19 at 13:30