storybook: Addon-docs: Source doc block Typescript support

Describe the bug As documented in the Technical Preview guide, using typescript without passing sourceLoaderOptions: null into the docs preset causes the following error:

Variable '__MODULE_DEPENDENCIES__' implicitly has an 'any[]' type

This is unfortunately not fixed by updating the storybook tsconfig.json to use "noImplicitAny": false.

To Reproduce Steps to reproduce the behavior:

  1. Write a story for addon-docs using Typescript and the docs preset
  2. Run storybook

Expected behavior Docs page loads, as usual, and a code snippet is available for the story.

Screenshots If applicable, add screenshots to help explain your problem.

Code snippets presets.js:

{
  name: '@storybook/addon-docs/react/preset',
  options: {
    sourceLoaderOptions: null,
  },
}

System: Environment Info:

System: OS: macOS 10.14.5 CPU: (16) x64 Intel® Core™ i9-9880H CPU @ 2.30GHz Binaries: Node: 10.16.0 - /usr/local/opt/node@10/bin/node Yarn: 1.17.3 - ~/workspace/component-library/node_modules/.bin/yarn npm: 6.9.0 - /usr/local/opt/node@10/bin/npm Browsers: Chrome: 76.0.3809.100 Safari: 12.1.1 npmPackages: @storybook/addon-a11y: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/addon-actions: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/addon-docs: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/addon-knobs: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/addon-links: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/addon-viewport: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/addons: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/preset-scss: 1.0.2 => 1.0.2 @storybook/preset-typescript: 1.1.0 => 1.1.0 @storybook/react: ^5.2.0-beta.36 => 5.2.0-beta.38 @storybook/theming: ^5.2.0-beta.36 => 5.2.0-beta.38

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 15
  • Comments: 69 (28 by maintainers)

Most upvoted comments

A temporary solution if you use awesome-typescript-loader:

/* tsconfig.json */
{
  "compilerOptions": { },
  "awesomeTypescriptLoaderOptions": {
    "ignoreDiagnostics": [7005]
  }
}

Not ideal, but it works.

Any updates on this? We’re trying to use storybook addons with TS and can’t get past this even with the workarounds. Continue to receive “Variable ‘MODULE_DEPENDENCIES’ implicitly has an ‘any[]’ type.”

Currently have tried updating storybook to 5.3.0-beta.16 and tried the other workarounds mentioned here. Thanks

A temporary solution if you use awesome-typescript-loader:

/* tsconfig.json */
{
  "compilerOptions": { },
  "awesomeTypescriptLoaderOptions": {
    "ignoreDiagnostics": [7005]
  }
}

Not ideal, but it works.

I just updated from 5.1 to 5.2.5 today and started getting this error, without installing addon-docs yet. This solution worked for me, although I have to say it’s not really clear to my why.

I have update both @storybook/reactand @storybook/addon-docs to 5.3.0-rc.4 but keep getting the error message TS7005: Variable '__MODULE_DEPENDENCIES__' implicitly has an 'any[]' type.

I’m not using the preset and also I’m new to webpack so probably I made some mistakes. Here is my webpack.config.js:


module.exports = {
    node: {
        fs: 'empty',
        child_process: 'empty'
    },
    resolve: {
        modules: [
            'node_modules',
        ],
        extensions: [".ts", ".tsx"],
        symlinks: true
    },
    module: {
        rules: [
            {
                test: /\.(ts|tsx)$/,
                use: [
                    {
                        loader: require.resolve('awesome-typescript-loader')
                    },
                    {
                        loader: require.resolve('react-docgen-typescript-loader')
                    },
                ]
            },
            {
                test: /\.(stories|story)\.[tj]sx?$/,
                loader: require.resolve('@storybook/source-loader')
            }
        ]
    },
    externals: {
        'class-transformer': 'class-transformer'
    }
};

@sami616 @sergiop I install react-docgen-typescript-loader version 3.2.1 I found some code in node_modules/react-docgen-typescript-loader/dist/generateDocgenCodeBlock

var setDefaultValue = function(defaultValue) {
    return typescript_1.default.createPropertyAssignment(
      typescript_1.default.createLiteral('defaultValue'),
      // Use a more extensive check on defaultValue. Sometimes the parser
      // returns an empty object.
      defaultValue != null && typeof defaultValue === 'object' && 'value' in defaultValue && typeof defaultValue.value === 'string'
        ? typescript_1.default.createObjectLiteral([
            typescript_1.default.createPropertyAssignment(
              typescript_1.default.createIdentifier('value'),
              typescript_1.default.createLiteral(defaultValue.value),
            ),
          ])
        : typescript_1.default.createNull(),
    );
  };

&& typeof defaultValue.value === 'string'

this condition limit the typeof defaultProps.

And In the newest version 3.3.0 react-docgen-typescript-loader, It supoort string、number、boolean

https://github.com/strothj/react-docgen-typescript-loader/blob/master/src/generateDocgenCodeBlock.ts

const setDefaultValue = (
    defaultValue: { value: string | number | boolean } | null,
  ) =>
    ts.createPropertyAssignment(
      ts.createLiteral("defaultValue"),
      // Use a more extensive check on defaultValue. Sometimes the parser
      // returns an empty object.
      defaultValue != null &&
        typeof defaultValue === "object" &&
        "value" in defaultValue &&
        (typeof defaultValue.value === "string" ||
          typeof defaultValue.value === "number" ||
          typeof defaultValue.value === "boolean")
        ? ts.createObjectLiteral([
            ts.createPropertyAssignment(
              ts.createIdentifier("value"),
              ts.createLiteral(defaultValue!.value),
            ),
          ])
        : ts.createNull(),
    );

@zerofront you’ll need a Typescript type for the component. You can instead use export const Button: React.FC<BaseButtonProps> = props => {...}

@zerofront @enagy27 yesterday I discovered that my issue (that was apparently the same of @zerofront) was caused exactly by the return type on function.

This fixed for me:

- import React from 'react'
+ import React, { FC } from 'react'

- export const Button: React.FC<Props>
+ export const Button: FC<Props>

Source: https://github.com/strothj/react-docgen-typescript-loader/issues/42#issuecomment-535090697 And partially this note could be related: https://github.com/strothj/react-docgen-typescript-loader#react-component-class-import

I hope this can help.

@zerofront I can confirm updating react-docgen-typescript-loader to 3.3.0 will solve the issue. Thanks. Screenshot 2019-10-10 at 12 00 16

Now that docs has been released I may be able to take some time to update cra-ts-kitchen-sink to make sure we’re all on the same page for configuration 🙂 it may be a week or so though… for now I’ll provide my config:

.storybook/addons.js

import '@storybook/addon-knobs/register';
import '@storybook/addon-a11y/register';
import '@storybook/addon-actions/register';

.storybook/config.js

import { configure, addDecorator, addParameters } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';
import { withKnobs } from '@storybook/addon-knobs';

import theme from './theme';
import '../stylesheets/gusto.scss';

// This file overrides styles from the global Gusto
// styles which interfere with Storybook styles
import './storybook.scss';

// Is your addon not showing up? Try looking for a `register` function
// and add it to .storybook/addons.js
addDecorator(withA11y);
addDecorator(withKnobs);

addParameters({
  // storybook built-in
  // more info available here:
  // https://storybook.js.org/docs/configurations/options-parameter/
  options: {
    showPanel: true,
    panelPosition: 'right',
    // https://storybook.js.org/docs/configurations/theming/
    theme,
  },
  knobs: {
    escapeHTML: false,
  },
  // viewport structure here:
  // https://github.com/storybookjs/storybook/tree/master/addons/viewport#use-custom-set-of-devices
  // viewport: {
  //   defaultViewport: 'iphone6',
  //   type: 'mobile',
  // },
});

configure(require.context('../src', true, /\.stories\.(js|jsx|ts|tsx|mdx)$/), module);

.storybook/presets.js

const path = require('path');

module.exports = [
  '@storybook/preset-scss',
  {
    name: '@storybook/preset-typescript',
    options: {
      // Point the loader here to override the root "noEmit" compilerOption
      tsLoaderOptions: {
        // Transpile only means no type-checking from storybook, which greatly speeds up
        // builds. Types will be checked as part of the normal build process. This may also
        // be necessary for loading story source
        transpileOnly: true,
        configFile: path.resolve(__dirname, 'tsconfig.json'),
      },
      // We must use our config to ensure props and their comments are loaded
      tsDocgenLoaderOptions: {
        tsconfigPath: path.resolve(__dirname, 'tsconfig.json'),
        // https://github.com/styleguidist/react-docgen-typescript#parseroptions
        propFilter: prop => {
          if (prop.parent) {
            return !prop.parent.fileName.includes('node_modules/@types/react/');
          }

          return true;
        },
      },
    },
  },
  '@storybook/addon-docs/react/preset',
];

.storybook/theme.js

I can’t share this because it’s internal to my company, but it’s referenced in config.js.

.storybook/tsconfig.json

This file only serves to remove configurations in the root tsconfig.json that wouldn’t make sense here in storybook.

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "noEmit": false
  }
}

The TS instructions point you to react-docgen-typescript-loader which says to install addon-info but earlier in the documentation doesn’t it says addon-docs is a replacement for addon-info? Would be super helpful to see a working setup of this with TS or some clear instructions in one place specifically for setting up addon-docs with TS.

Happy to contribute and help out but need to understand how these pieces fit together first! 👍

@enagy27 You rock for figuring this out. I’m hoping that @libetl will come back online at some point in 5.3, and we can just upgrade source-loader so that these workarounds are not needed. Fingers crossed! 🤞

Hello @shilman Thanks for the amazing support for docs combined with storybook. I updated to 5.3.0-rc.5 and I still get the error TS7005: Variable '__MODULE_DEPENDENCIES__' implicitly has an 'any[]' type.

It works only if I add ignoreDiagnostics: [7005] to the ts-loader configuration as shown below.

file main.js:

const { addons } = require('@storybook/addons');
const path = require('path');
const tsImportPluginFactory = require('ts-import-plugin')

module.exports = {
  stories: ['../packages/**/*.stories.(tsx|mdx)'],
  presets: [
    {
      name: '@storybook/preset-typescript',
      options: {
        tsLoaderOptions: {
          configFile: path.resolve(__dirname, 'tsconfig.json'),
          ignoreDiagnostics: [7005],
          getCustomTransformers: () => ({
            before: [ tsImportPluginFactory(
              {
                libraryName: 'antd',
                style: 'css',
                libraryDirectory: 'es'
              }
            ) ]
          }),
        },
        tsDocgenLoaderOptions: {
          tsconfigPath: path.resolve(__dirname, 'tsconfig.json'),
        },
        forkTsCheckerWebpackPluginOptions: {
          colors: false, // disables built-in colors in logger messages
        },
        include: [path.resolve(__dirname, "../packages")]
      },
    },
    {
      name: '@storybook/addon-docs/preset',
      options: {
      }
    }],
  addons: [
    '@storybook/addon-docs/register',
    '@storybook/addon-knobs/register',
    '@storybook/addon-actions/register',
    '@storybook/addon-links/register'
  ],
};

Follow up, I got it working using the transpileOnly option mentioned by @enagy27. I am using presets instead of full webpack configs, this is currently my presets.js. No changing in the tsconfig.json:

// presets.js
const path = require("path");

module.exports = [
	{
		name: "@storybook/preset-typescript",
		options: {
			tsLoaderOptions: {
				configFile: path.resolve(__dirname, "../tsconfig.json"),
				transpileOnly: true,
			},
			tsDocgenLoaderOptions: {
				tsconfigPath: path.resolve(__dirname, "../tsconfig.json"),
			},
			include: [path.resolve(__dirname, "../src")],
		},
	},
	{
		name: "@storybook/addon-docs/react/preset",
		options: {
			configureJSX: true,
			//sourceLoaderOptions: null,
		},
	},
];

@jalooc please check out 5.3 beta. Tons of improvements to the props table.

@sami616, as already told, I want to open a bug report on this, but before to do it I need to investigate a little on the codebase, to understand if the source of the issue is storybook or react-docgen-typescript-loader. In this way I’ll open the issue on the right project.

Ignore my comment, yes im having the same issue.

Hi, @enagy27. thanks for this. I have got this working with the config you shared。but there is still some promble. It cannot generate component description and props description when I write component with tsx. but it work with jsx。 image image image

Hi. Can someone provide an example repo where storybook with react typescript and docs are working?

I’ve found a workaround!

  • Instead of using sourceLoaderOptions: null, I used transpileOnly: true in my tsLoaderOptions
  • Follow the workaround in #8055, where there cannot be a top-level parameters variable
  • For some reason, the use of right-hand statements such as as 'optionA' | 'optionB' failed here and had to be converted to left-hand type declarations.

This fails:

const colors = {
  primary: 'primary',
  secondary: 'secondary',
};

const color = radios('color', colors, colors.primary) as ButtonColor;

This works:

const colors: Record<string, ButtonColor> = {
  primary: 'primary',
  secondary: 'secondary',
};

const color = radios('color', colors, colors.primary);

In hindsight this seems like an understandable source-loader issue with type inference 🤔 anyway, hope this helps!

No longer seeing issues with rc.4, but no source 😞 Though it looks like this is also marked in #6641, so now that the errors are no longer present, this issue may be a duplicate