Nov 2019

I keep struggling with setting up projects that use TypeScript, Preact and Emotion in combination. The problem is that without the proper configuration, JSX will either not be transpiled or it will call the wrong function at runtime.

Although I haven’t looked particularly deep into this I was able to solve it. The issue stems from when you make TS aware of JSX by pointing it to Preact’s h function instead of React.createElement but then you need to go back and tell Emotion where to find jsx.

In order for all the transpilation to work fine with with Preact + TypeScript, you need to configure TypeScript accordingly:

// tsconfig.json
{
    "compilerOptions": {
        "jsx": "react",
        "jsxFactory": "h"
    }
}

Emotion recommends doing the following:

// .babelrc
{
  "presets": ["@emotion/babel-preset-css-prop"],
  "plugins": [
    "emotion",
    ["@babel/plugin-transform-react-jsx"]
  ]
}

But this alone is not enough to get Emotion’s css prop working! You will get something like jsx is undefined. So in your components your need to tell it to use Preact’s h function as the JSX factory. You can do that either by renaming the import or by using a pragma:

// $mycomponent.tsx
/* @jsx h */ // either this...
import { jsx as h } from '@emotion/core'; // ...or this