You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Storybook 8与Angular 18渲染函数类型错误:无法赋值给ArgsStoryFn

Storybook 8.3.4 + Angular 18.2.6:带EventEmitter的组件故事类型错误解决方法

问题场景

为包含@Output EventEmitter的Angular组件编写Storybook故事时,出现类型不兼容错误:故事中定义的args参数类型与Storybook渲染器期望的类型不匹配,提示缺少组件的私有成员(如示例中的store)。移除@Output后问题消失,但业务需要保留事件发射器,临时用any规避类型检查并非最佳实践。

组件示例代码:

class MyComponent {
  @Output() someEvent = new EventEmitter<any>();

  constructor(
    private readonly store: Store,
  ) {}
  // 其他属性和方法
}

原故事代码(触发错误):

export default meta;
type Story = StoryObj<MyComponent>;

export const Basic: Story = {
  render: (args: MyComponent) => ({
    props: {
      ...args,
    },
  }),
  args: {},
};

错误提示:

Type '(args: MyComponent) => { props: { someEvent: EventEmitter<...>; }; }' is not assignable to type 'ArgsStoryFn<AngularRenderer, TransformInputSignalType<TransformOutputSignalType>>'.
Types of parameters 'args' and 'args' are incompatible.
Type 'TransformInputSignalType<TransformOutputSignalType>' is missing the following properties from type 'MyComponent': store

原因分析

Storybook的Angular渲染器会对组件的输入输出属性做类型转换(比如处理Angular 18的信号输入、事件发射器的类型映射),最终传递给render函数的args只包含可用于模板绑定的公共属性(@Input、@Output),不包含组件的私有成员(如store)。而直接用MyComponent作为StoryObj的泛型参数,会让TypeScript期望args包含组件的所有成员(包括私有属性),导致类型不匹配。

正确解决方案

方案1:使用Storybook的ComponentPropsType提取可绑定属性

利用Storybook提供的ComponentPropsType工具类型,自动提取组件的可绑定公共属性,排除私有成员:

import { Meta, StoryObj, ComponentPropsType } from '@storybook/angular';
import { MyComponent } from './my.component';

const meta: Meta<MyComponent> = {
  component: MyComponent,
};
export default meta;

// 使用ComponentPropsType获取组件的可绑定属性类型
type Story = StoryObj<ComponentPropsType<MyComponent>>;

export const Basic: Story = {
  render: (args) => ({
    props: args,
  }),
  args: {},
};

或者更简洁地直接复用meta的类型:

type Story = StoryObj<typeof meta>;

方案2:手动排除私有成员

如果需要更精细控制类型,可以手动排除组件的私有属性:

import { Meta, StoryObj } from '@storybook/angular';
import { MyComponent } from './my.component';

const meta: Meta<MyComponent> = {
  component: MyComponent,
};
export default meta;

// 排除私有成员store
type MyComponentProps = Omit<MyComponent, 'store'>;
type Story = StoryObj<MyComponentProps>;

export const Basic: Story = {
  render: (args) => ({
    props: args,
  }),
  args: {},
};

验证效果

以上两种方案都能让args类型与Storybook渲染器期望的类型匹配,消除类型错误,同时保留EventEmitter的类型安全检查,无需使用any。

内容的提问来源于stack exchange,提问作者Ben Thomson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 03:15:59