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

如何在使用Children.toArray过滤组件子元素时实现类型安全?

实现类型安全的React子元素过滤(替代any类型)

原问题代码

export function Nav({
  children,
}: MenuProps): JSX.Element {
  const desktopItems = useMemo(
    () =>
      Children.toArray(children.props.children)
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        .filter((m: any) => m.props.display === 'Always')
        .map((m) => <> {m} </>),
    [children.props.children],
  );

要解决any类型带来的类型不安全问题,可通过定义子组件Props类型+类型守卫函数实现,具体操作如下:


  • 定义子组件的Props类型
    先明确导航子项组件的Props结构,示例如下:
// 假设子组件为NavItem,定义其Props类型
type NavItemProps = {
  display: 'Always' | 'MobileOnly' | 'DesktopOnly';
  // 按需添加子组件所需的其他Props字段
};
  • 编写类型守卫函数
    通过类型守卫判断子元素是否为符合要求的NavItem组件,让TypeScript自动推导类型:
import React, { ReactNode, isValidElement } from 'react';

function isNavItem(element: ReactNode): element is React.ReactElement<NavItemProps> {
  // 先验证是否为有效React元素,再检查props是否包含display字段
  return isValidElement(element) && 'display' in element.props;
}
  • 重构过滤逻辑,移除any类型
    将原代码中的filter替换为类型守卫,TypeScript会自动识别过滤后的元素类型:
export function Nav({ children }: MenuProps): JSX.Element {
  const desktopItems = useMemo(() => {
    const childElements = Children.toArray(children.props.children);
    
    return childElements
      .filter(isNavItem) // 过滤出符合类型的子元素
      .filter(item => item.props.display === 'Always') // 筛选display为Always的项
      .map(item => <> {item} </>);
  }, [children.props.children]);

  // 补充你的渲染逻辑
  return <nav>{desktopItems}</nav>;
}
  • 额外优化:明确MenuProps的类型
    如果MenuProps中的children类型不够清晰,建议定义更精确的类型,避免访问children.props.children时出现类型警告:
type MenuProps = {
  children: React.ReactElement<{
    children: React.ReactNode;
  }>;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:00:19