Advanced Static Types in TypeScript

This course explores the capabilities of TypeScript’s type system and shows how to use advanced static types in practice.

Watch the Course

TypeScript 2.6: JSX Fragment Syntax

TypeScript 2.6 added support for JSX fragments. Within .tsx files, you can now use the new <>...</> syntax to create a fragment.

Motivation Behind JSX Fragments

In React, it's a common pattern to return multiple elements from a component. For instance, let's say we want to render multiple list items within the following component:

class List extends React.Component {
    render() {
        return (
            <ul>
                <ListItems />
                <li>Item 3</li>
            </ul>
        );
    }
}

However, in our ListItems component, we cannot simply return multiple adjacent JSX elements like this:

class ListItems extends React.Component {
    render() {
        return (
            <li>Item 1</li>
            <li>Item 2</li>
        );
    }        
}

Adjacent JSX elements must be wrapped in an enclosing element, so we could add a wrapping div element:

class ListItems extends React.Component {
    render() {
        return (
            <div>
                <li>Item 1</li>
                <li>Item 2</li>
            </div>
        );
    }        
}

Unfortunately, adding such a wrapper breaks the structure of our list. Our ListItems component currently renders the following DOM elements:

<ul>	
    <div>
        <li>Item 1</li>
        <li>Item 2</li>
    </div>
    <li>Item 3</li>
</ul>

Note that the <div> doesn't belong in there. We can get rid of it by using the JSX fragment syntax instead:

class ListItems extends React.Component {
    render() {
        return (
            <>
                <li>Item 1</li>
                <li>Item 2</li>
            </>
        );
    }
}

A fragment lets us group multiple JSX elements without adding an extra wrapper node. Now, our List component renders the expected markup:

<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>

Alternatively, we could've explicitly written React.Fragment instead of using the new JSX syntax:

class ListItems extends React.Component {
    render() {
        return (
            <React.Fragment>
                <li>Item 1</li>
                <li>Item 2</li>
            </React.Fragment>
        );
    }
}

The two versions of our ListItems component are equivalent and render exactly the same output (given that we compile our JSX for use with React).

Compiling JSX Fragments with TypeScript

Here's our ListItems component with the new JSX syntax again:

class ListItems extends React.Component {
    render() {
        return (
            <>
                <li>Item 1</li>
                <li>Item 2</li>
            </>
        );
    }
}

If we compile the .tsx file with --jsx react (and --target es2015), the following JavaScript is emitted:

class ListItems extends React.Component {
    render() {
        return (React.createElement(React.Fragment, null,
            React.createElement("li", null, "Item 1"),
            React.createElement("li", null, "Item 2")));
    }
}

The compiler replaces the short fragment syntax by a call to the React.createElement() method and passes it React.Fragment as the first argument.

If we compiled our ListItems component with --jsx preserve (and --target es2015) instead, our JSX would be emitted unchanged, set aside whitespace:

class ListItems extends React.Component {
    render() {
        return (<>
                <li>Item 1</li>
                <li>Item 2</li>
            </>);
    }
}