Storybook: Add TypeScript support via Babel 7

Created on 26 Oct 2018  路  20Comments  路  Source: storybookjs/storybook

Seeing as adding TypeScript support via Babel 7 is getting a lot of traction (see e.g. https://github.com/facebook/create-react-app/pull/4837 for a high profile example), it would be nice for Storybook to support this possibility out of the box.

What I expect to be possible, is for me to add the proper values to my .babelRc and for Storybook to then be able to compile TypeScript to JS.

Example .babelrc

{
  "presets": [
    ["@babel/preset-react", {"development": true}],
    ["@babel/preset-typescript"],
    ["@babel/env", { "modules": false }]
  ],
  "plugins": [
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread"
  ]
}

However this does not work. Storybook only applies these rules to javascript files in the webpack configuration. You also have to create a corresponding webpack configuration file:

module.exports = (storybookBaseConfig, configType) => {
    storybookBaseConfig.resolve.extensions.push('.ts', '.tsx');
    storybookBaseConfig.module.rules[0].test = /\.(mjs|jsx?|tsx?)$/;
    return storybookBaseConfig;
};

Would it be possible to include the typescript files in the test and the extensions per default? I can't see any downside for people not using typescript, as nothing will change for them.

react cra typescript

Most helpful comment

Now that this is official in CRA, it would be great to add this out-of-the-box.

All 20 comments

I am also trying to add support for that via Babel. How did you get around the Error: Requires Babel "^7.0.0-0", but was loaded with "6.26.3". error?

I already installed @babel/core instead of babel-core

Edit: figured it out, I was missing to upgrade babel-loader to v8.0.0

(I updated the configuration above. I have it working with it, except for decorators which require an additional plugin)

Great idea @GeeWee , PR is welcome

Trying to do this just yesterday with a create-react-app with Typescript enabled and encountered that baseurl isn't handled well, or is isn't compatible with create-react-app's required parameters (such as noemit) even with the above tweaks.

Now that this is official in CRA, it would be great to add this out-of-the-box.

Just adding this resolved the issue for me.

module.exports = (baseConfig, configType, config) => {
    config.resolve.extensions.push('.ts', '.tsx');
    config.module.rules[0].test = /\.(mjs|jsx?|tsx?)$/;
    return config;
};

However, the docs suggest the following:

module.exports = (baseConfig, env, config) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
      presets: [['react-app', { flow: false, typescript: true }]],
    },
  });
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};

If we're OK with this approach, I can put together a PR that looks for a tsconfig.json in root, and if present, adds support in the same way that we do for CSS modules (below).
https://github.com/storybooks/storybook/blob/next/app/react/src/server/cra-config.js

The config above works for me as well. Note that you'll have to make a decision whether or not to support decorators, they're a separate plugin.

I think we should (by default) follow the approach used by CRA - so when we detect react-scripts we add only the behaviours expected.

Otherwise, users can do what they could always do and extend.

Edit: I'll work on this today and submit a PR ;)

@mrmckeb this one worked for me:

module.exports = (baseConfig, env, config) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
      presets: [['react-app', { flow: false, typescript: true }]],
    },
  });
  config.resolve.extensions.push('.ts', '.tsx');
  return config;

Thanks!

Hi all, if anyone would like to take a look at #4824 and leave feedback, please do.

It's works perfectly for me when testing locally.

This doesn't support the config files as TypeScript.

For this:

// config.tsx
addDecorator(story => (
    <IntlProvider locale="en" messages={translations}>
        <>
            <BoxSizing />
            <Typography />
            {story()}
        </>
    </IntlProvider>
));
addDecorator(story => (
    <ThemeProvider theme={defaultTheme}>{story()}</ThemeProvider>
));

to work I still need to add

//webpack.config.js
module.exports = (storybookBaseConfig, configType) => {
  storybookBaseConfig.module.rules[0].test = /\.(mjs|jsx?|tsx?)$/;

  return storybookBaseConfig;
};

@Itrulia It was never intended to sorry, this was intended for project files, and I never tested for or thought to support this. Apologies if this caused you any inconvenience.

I'm concerned that your change suggested above could be an issue as it would force all typescript to be passed by rule[0], which is not the rule for CRA.

@igor-dv This could be an order of operations issue. Should we add the CRA config earlier?

I assume it happens because CRA includes only files from src dir into its rules, and .storybook is not located there. We can add it to the CRA preset too...

@igor-dv Maybe that's best. To limit the impact, we could specifically add the .storybook directory alongside src. I can take a look at that over the weekend if that's OK? Or if it's more urgent, I can make some time before then.

Take your time 馃憤 thanks

Is it also going to be configurable via the -c option? We for example are using -c config/storybook

edit: Also thanks for looking in to it 馃憤

It should =)

@igor-dv Please see #4902

The fix is merged.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

43081j picture 43081j  路  61Comments

hansthinhle picture hansthinhle  路  57Comments

ChucKN0risK picture ChucKN0risK  路  74Comments

Olian04 picture Olian04  路  78Comments

p3k picture p3k  路  61Comments