The Wayback Machine - https://web.archive.org/web/20190604002214/https://github.com/KonstantinSimeonov/tsx-control-statements
Skip to content
Control flow JSX/TSX elements that get compiled to plain old javascript.
Branch: master
Clone or download

README.md

tsx-control-statements

Build Status Coverage Status Gitter chat

Basically jsx-control-statements, but for the typescript compiler toolchain. Works for both javascript and typescript.

Typescript version Build status
2.4.x tests passing
2.5.x tests passing
2.6.x tests passing
2.7.x tests passing
2.8.x tests passing
2.9.x tests passing
3.0.x tests passing
3.1.x tests passing
3.2.x tests passing
3.3.x tests passing
3.4.x tests passing
next tests passing

It compiles tsx

  • Control statements transpile to type correct typescript before type checking
    • Editors like visual studio code cannot infer that some additional transpilation will occur and will complain (check out a workaround here)
  • Test it: yarn && yarn build && yarn test
    • Tests include behaviour compatibility tests with jsx-control-statements and tests whether tsx control statements render the same elements as components using plain ts in tsx.

It compiles javascript jsx

  • Setting "allowJs" to true in tsconfig.json should do the trick.

No dependence on any frontend framework

  • The transformer works solely on the typescript ast and has nothing to do with React, React Native, Vue and so on. It just transforms jsx.

Known limitations:

  • [js, ts] I haven't found any way of integrating this into create-react-app scaffold project without ejecting the scripts and modifying them
  • [js, ts] Various CLIs (tsc, ts-register, ts-node) feature no flag (that I know of) that allows for addition of custom transformers
  • [ts] The isolatedModules flag currently causes build errors for typescript files, since the typings currently live in a namespace
  • [ts] Cannot work with various "smart" plugins that instead of invoking the typescript compiler rather strip the types and handle the code as javascript. This includes tools like:
    • @babel/preset-typescript
    • @babel/plugin-transform-typescript

What code is emitted?

If - Ternary operators

const SongRelatedThingy = ({ songList }: { songList: string[] }) => (
    <p>
        <If condition={songList.includes('Gery-Nikol - Im the Queen')}>
            good taste in music
        </If>
    </p>
)

// will transpile to
const SongRelatedThingy = ({ songList }: { songList: string[] }) => (
    <p>
        {songList.includes('Gery-Nikol - Im the Queen')
		? 'good taste in music'
		: null
	}
    </p>
)

With - Immediately invoked function expression

const Sum = () => (
    <p>
        <With a={3} b={5} c={6}>
            {a + b + c}
        </With>
    </p>
)

// becomes
const Sum = () => (
    <p>
        {((a, b, c) => a + b + c))()}
    </p>
)

For - Array.from calls

  • Since Array.from can be provided with an iterator or an array-like as it's first parameter, it is much more flexible than [].map.
const Names = ({ names }: { names: string[] }) => (
    <ol>
        <For each="name" of={names} index="i">
            <li key={name}>
		{i}<strong>{name}</strong></li>
        </For>
    </ol>
)

// Will become
const Names = ({ names }: { names: string[] }) => (
    <ol>
        {Array.from(names, (name, i) => (
		<li key={name}>
			{i}
			<strong>{name}</strong>
		</li>
	)}
    </ol>
)

Choose/When/Otherwise - Nested ternary operators.

const RandomStuff = ({ str }: { str: string }) => (
    <article>
        <Choose>
            <When condition={str === 'ivan'}>
                ivancho
                </When>
            <When condition={str === 'sarmi'}>
                <h1>yum!</h1>
            </When>
            <Otherwise>
                im the queen da da da da
            </Otherwise>
        </Choose>
    </article>
)

// transpiles to
const RandomStuff = ({ str }: { str: string }) => (
    <article>
	{str === 'ivan'
		? 'ivancho'
		: (str === 'sarmi'
			? React.createElement('h1', null, 'yum!')
			: 'im the queen da da da da')
	}
    </article>
)
  • Otherwise tag at the end is optional - if not provided, whenever no When's condition did match, nothing will be rendered.

Cookbook (example setups incoming)

Is it a drop-in replacement of jsx-control-statements?

  • For javascript, yes.

  • This should be the case for typescript too, but I haven't tested it too much.

  • In your code:

// commonjs
const transformer = require('tsx-control-statements').default();

// ts
import transformer from 'tsx-control-statements';
  • If typescript complains about typings:
import 'tsx-control-statements/index.d';

Reasons to not use any control statements for jsx:

  • Hard to statically type
  • Not part of the standard
  • Not ordinary jsx elements
  • Requires extra dependencies to use
  • Many typescript tools do not support custom transformers in a convenient way
You can’t perform that action at this time.