Docs
Storybook Docs

TypeScript

Storybook 提供集成的 TypeScript 体验,包括零配置设置和 API、插件和故事的内置类型。

¥Storybook provides an integrated TypeScript experience, including zero-configuration setup and built-in types for APIs, addons, and stories.

使用 TypeScript 配置 Storybook

¥Configure Storybook with TypeScript

Storybook 的配置文件(即 main.ts)被定义为用 TypeScript 编写的 ESM 模块,为你提供支持现有框架的基线配置,同时使你能够在编辑器中进行更严格的类型检查和自动补齐。下面是配置文件的简略版本。

¥Storybook's configuration file (i.e., main.ts) is defined as an ESM module written in TypeScript, providing you with the baseline configuration to support your existing framework while enabling you stricter type-checking and autocompletion in your editor. Below is an abridged configuration file.

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  // Required
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  // Optional
  addons: ['@storybook/addon-essentials'],
  docs: {
    autodocs: 'tag',
  },
  staticDirs: ['../public'],
};
 
export default config;

有关更多详细信息和其他属性,请参阅 主要配置 API 参考

¥See the main configuration API reference for more details and additional properties.

如果使用 @storybook/builder-vite,请参阅 Vite 构建器 TypeScript 文档

¥See the Vite builder TypeScript documentation if using @storybook/builder-vite.

扩展默认配置

¥Extending the default configuration

开箱即用,Storybook 可以与各种第三方库配合使用,使你无需进行任何额外配置即可安全地访问和记录组件的元数据(例如,props)。它依赖于 react-docgen,这是一个快速且高度可定制的解析器,用于处理 TypeScript 文件以推断组件的元数据并自动生成类型,以提高性能和类型安全性。如果你需要为特定用例场景自定义默认配置,你可以调整 Storybook 配置文件并提供所需的选项。下面列出了可用的选项及其使用方法示例。

¥Out of the box, Storybook is built to work with a wide range of third-party libraries, enabling you to safely access and document metadata (e.g., props) for your components without any additional configuration. It relies on react-docgen, a fast and highly customizable parser to process TypeScript files to infer the component's metadata and generate types automatically for improved performance and type safety. If you need to customize the default configuration for a specific use case scenario, you can adjust your Storybook configuration file and provide the required options. Listed below are the available options and examples of how to use them.

选项描述
check适用于基于 Webpack 的项目。
在 Storybook 中启用类型检查
typescript: { check: true },
checkOptions需要启用 check 选项。
配置 fork-ts-checker-webpack-plugin 插件
typescript: { checkOptions: {},},
reactDocgen配置 Storybook 使用的 TypeScript 解析器。
可用选项:react-docgen(默认)、react-docgen-typescript false
typescript: { reactDocgen: 'react-docgen'},
reactDocgenTypescriptOptions需要 reactDocgen 选项为 react-docgen-typescript
为每个构建器配置 react-docgen-typescript-plugin 插件
typescript: { reactDocgen: 'react-docgen-typescript', reactDocgenTypescriptOptions: {},},
skipCompiler禁用通过编译器解析 Typescript 文件
typescript: { skipCompiler:false,},
.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  typescript: {
    check: false,
    checkOptions: {},
    skipCompiler: false,
  },
};
 
export default config;

typescript 配置选项有其他选项可用。有关更多信息,请参阅 config.typescript API reference

¥Additional options are available for the typescript configuration option. See the config.typescript API reference for more information.

使用 TypeScript 编写故事

¥Write stories with TypeScript

Storybook 提供零配置 TypeScript 支持,允许你使用此语言编写故事而无需额外配置。你可以使用这种格式来提高类型安全性和代码完成度。例如,如果你正在测试 Button 组件,则可以在故事文件中执行以下操作:

¥Storybook provides zero-config TypeScript support, allowing you to write stories using this language without additional configuration. You can use this format for improved type safety and code completion. For example, if you're testing a Button component, you could do the following in your story file:

Button.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { Button } from './Button';
 
const meta: Meta<typeof Button> = {
  component: Button,
};
 
export default meta;
type Story = StoryObj<typeof Button>;
 
//👇 Throws a type error if the args don't match the component props
export const Primary: Story = {
  args: {
    primary: true,
  },
};

上面的示例结合使用 TypeScript 的强大功能和导出的泛型类型(MetaStoryObj)来告诉 Storybook 如何推断组件的元数据和组件输入的类型(例如,props)。这可以极大地改善开发者的体验,因为它可以让你的 IDE 向你展示 Storybook 注入了哪些属性。

¥The example above uses the power of TypeScript in combination with the exported generic types (Meta and StoryObj) to tell Storybook how to infer the component's metadata and the type of the component's inputs (e.g., props). This can greatly improve the developer experience by letting your IDE show you what properties are injected by Storybook.

TypeScript 4.9 支持

¥TypeScript 4.9 support

假设你正在使用 TypeScript 4.9+ 的项目上工作,你可以更新组件故事以使用新的 satisfies 运算符,以确保对组件故事进行更严格的类型检查。例如:

¥Assuming that you're working on a project that uses TypeScript 4.9+, you can update your component stories to use the new satisfies operator to ensure stricter type checking for your component stories. For example:

Button.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta } from '@storybook/<your-framework>';
 
import { Button } from './Button';
 
const meta = {
  component: Button,
} satisfies Meta<typeof Button>; // 👈 Satisfies operator being used for stricter type checking.
 
export default meta;

现在,当你定义故事或更新现有故事时,你会自动收到通知,告知你缺少必需的 arg。但是,你不仅限于在组件级别使用 satisfies 运算符。如果需要,你也可以在故事级别使用它。例如:

¥Now, when you define a story or update an existing one, you'll automatically get notified that you're missing a required arg. However, you're not limited to using the satisfies operator at the component level. If you need, you can also use it at the story level. For example:

Button.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta, StoryObj } from '@storybook/your-framework';
 
import { Button } from './Button';
 
const meta = {
  component: Button,
} satisfies Meta<typeof Button>;
 
export default meta;
type Story = StoryObj<typeof meta>;
 
export const Example = {
  args: {
    primary: true,
    label: 'Button',
  },
} satisfies Story;

故障排除

¥Troubleshooting

satisfies 运算符未按预期工作

¥The satisfies operator is not working as expected

开箱即用,Storybook 支持几乎所有已经使用 TypeScript 4.9 或更高版本框架的 satisfies 运算符。但是,由于 Angular 和 Web Components 框架的限制,在应用此运算符以获得额外的类型安全性时,你可能会遇到问题。这主要是由于两个框架当前的实现方式,Storybook 几乎不可能确定组件属性是否是必需的。如果你遇到此问题,请在 GitHub 讨论 上打开支持请求。

¥Out of the box, Storybook supports the satisfies operator for almost every framework already using TypeScript version 4.9 or higher. However, due to the constraints of the Angular and Web Components framework, you might run into issues when applying this operator for additional type safety. This is primarily due to how both frameworks are currently implemented, making it almost impossible for Storybook to determine if the component property is required. If you encounter this issue, please open up a support request on GitHub Discussions.

Storybook 不会为外部包创建所需的类型

¥Storybook doesn't create the required types for external packages

如果你的项目依赖于第三方库并且未生成预期的类型,从而阻止你准确记录组件,你可以调整 Storybook 配置文件中的 reactDocgen 配置选项以使用 react-docgen-typescript 并包含所需的选项。例如:

¥If your project relies on a third-party library and the expected types are not being generated, preventing you from accurately documenting your components, you can adjust the reactDocgen configuration option in your Storybook configuration file to use react-docgen-typescript instead and include the required options. For example:

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  typescript: {
    reactDocgen: 'react-docgen-typescript',
    reactDocgenTypescriptOptions: {
      compilerOptions: {
        allowSyntheticDefaultImports: false,
        esModuleInterop: false,
      },
      // Filter out third-party props from node_modules except @mui packages.
      propFilter: (prop) =>
        prop.parent ? !/node_modules\/(?!@mui)/.test(prop.parent.fileName) : true,
    },
  },
};
 
export default config;

未为我的组件生成类型

¥The types are not being generated for my component

如果你正在使用 React 项目,则使用 react-docgen 库会自动为你的组件启用类型推断,以缩短构建时间并提高类型安全性。但是,你可能会遇到某些选项无法按预期工作的情况(例如 Enums、React 的 forwardRef)。这主要是由于 react-docgen 包的实现方式,这使得 Storybook 很难推断组件的元数据并自动生成类型。为了解决这个问题,你可以更新 Storybook 配置文件中的 typescript 配置选项以改用 react-docgen-typescript。例如:

¥If you're working with a React project, type inference is automatically enabled for your components using the react-docgen library for improved build times and type safety. However, you may run into a situation where some options may not work as expected (e.g., Enums, React's forwardRef). This is primarily due to how the react-docgen package is implemented, making it difficult for Storybook to infer the component's metadata and generate types automatically. To solve this, you can update the typescript configuration option in your Storybook configuration file to use react-docgen-typescript instead. For example:

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, react-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  typescript: {
    reactDocgen: 'react-docgen-typescript',
    // Provide your own options if necessary.
    // See https://storybook.js.org/docs/configure/typescript for more information.
    reactDocgenTypescriptOptions: {},
  },
};
 
export default config;

如果你仍然遇到问题,我们建议你使用默认沟通渠道(例如 GitHub 讨论)联系社区。

¥If you're still encountering issues, we recommend reaching out to the community using the default communication channels (e.g., GitHub discussions).