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

React Storybook+TypeScript中提取组件Props类型显示any的问题排查

React组件Props类型提取异常问题分析与解决方案

问题背景

在Storybook中开发React Button组件时,尝试通过React.ComponentProps<typeof Button>提取组件的Props类型,结果始终得到any类型。相关代码如下:

Button组件代码

import React, { useCallback } from 'react';
import { ButtonProps } from './types';

const Button = (props: ButtonProps) => {
  const { children, extraClasses, onClick } = props;
  const memoizedOnClick = useCallback(() => onClick?.(props), []);
  return (
    <button className={extraClasses} onClick={memoizedOnClick}>
      {children}
    </button>
  );
};

Button.defaultProps = {
  children: <b>Test Button</b>
};

export default Button;

尝试提取类型的代码

type DefaultButtonProps = React.ComponentProps<typeof Button>

ButtonProps定义

export interface ButtonProps extends HTMLButtonElement {
  children: ReactNode,
  extraClasses?: string;
  onClick?: (props: ButtonProps) => void
}

原因分析

  • 错误的继承目标:ButtonProps继承了HTMLButtonElement,这是DOM按钮元素的实例类型,而非React按钮组件接收的Props类型。React组件的Props类型应该使用官方封装的ButtonHTMLAttributes<HTMLButtonElement>,直接继承DOM实例类型会导致TypeScript无法正确推导组件Props,最终React.ComponentProps返回any。
  • 循环引用干扰:onClick的参数定义为ButtonProps本身,形成了类型循环引用,进一步破坏了TypeScript的类型解析逻辑。

修复方案

1. 修正ButtonProps的定义

将继承目标替换为React官方的按钮Props类型,并消除循环引用:

import { ReactNode, ButtonHTMLAttributes } from 'react';

export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  children: ReactNode;
  extraClasses?: string;
  // 用Omit移除onClick,避免循环引用
  onClick?: (props: Omit<ButtonProps, 'onClick'>) => void;
}
  • ButtonHTMLAttributes<HTMLButtonElement>包含了所有原生HTML按钮的Props(如disabled、type、name等),符合React组件Props的设计规范。
  • 使用Omit<ButtonProps, 'onClick'>作为onClick的参数类型,避免了循环引用问题。

2. 验证类型提取

此时再执行以下代码,DefaultButtonProps会正确解析为ButtonProps的完整类型:

import Button from './Button';
type DefaultButtonProps = React.ComponentProps<typeof Button>;

额外优化:修复useCallback依赖问题

原组件中useCallback的依赖数组为空,但内部使用了props和onClick,会导致闭包捕获旧值,引发逻辑错误。修正为:

const memoizedOnClick = useCallback(() => onClick?.(props), [onClick, props]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:25:36