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

TypeScript中如何实现支持可变数量泛型参数的React条件渲染组件

通用版实现方案

核心思路

完全可以实现支持任意数量属性的通用版本,核心依赖TypeScript的可变元组泛型和递归类型收窄能力,可以自动推导传入数组每个元素的原始类型,过滤掉null/undefined类型完成自动收窄,不需要为不同参数数量单独定义组件。

完整代码实现

import type { ReactNode } from "react";

// 基础类型定义
export type Maybe<T> = T | undefined | null;

// 类型工具:将Maybe元组的每个元素收窄为非空类型
type ExcludeNullishFromTuple<T extends Maybe<any>[]> = {
  [K in keyof T]: T[K] extends Maybe<infer U> ? U : never;
};

// 通用Only组件,支持任意长度的when数组
export function Only<T extends Maybe<any>[]>(props: {
  when: T;
  children: ReactNode | ((when: ExcludeNullishFromTuple<T>) => ReactNode);
}) {
  const { when, children } = props;
  // 检查所有元素都为真值
  const isAllTruthy = when.every(item => Boolean(item));
  if (!isAllTruthy) return null;
  return (
    <>
      {typeof children === "function"
        ? children(when as ExcludeNullishFromTuple<T>)
        : children}
    </>
  );
}

使用示例

直接传入任意长度的数组即可,回调参数会自动收窄为非空类型,无需额外的非空断言:

import { useState } from "react";

const MyComponent = (props: { value1: number; value2: string; value3: boolean }) => (
  <>
    <div>Value1: {props.value1}</div>
    <div>Value2: {props.value2}</div>
    <div>Value3: {props.value3 ? "是" : "否"}</div>
  </>
);

export function MyPage() {
  const [value1, setValue1] = useState<number>();
  const [value2, setValue2] = useState<string>();
  const [value3, setValue3] = useState<boolean>();

  setTimeout(() => {
    // 模拟异步请求
    setValue1(42);
    setValue2("foo");
    setValue3(true);
  }, 1000);

  return (
    <div>
      <Only when={[value1, value2, value3]}>
        {([value1, value2, value3]) => (
          <MyComponent value1={value1} value2={value2} value3={value3} />
        )}
      </Only>
    </div>
  );
}

可选优化:对象传参版本

如果觉得数组解构不够直观,还可以实现支持传入对象的版本,使用时可以直接按属性名解构,更适合参数较多的场景:

// 对象版本类型工具
type ExcludeNullishFromObject<T extends Record<string, Maybe<any>>> = {
  [K in keyof T]: T[K] extends Maybe<infer U> ? U : never;
};

export function OnlyObject<T extends Record<string, Maybe<any>>>(props: {
  when: T;
  children: ReactNode | ((when: ExcludeNullishFromObject<T>) => ReactNode);
}) {
  const { when, children } = props;
  const isAllTruthy = Object.values(when).every(item => Boolean(item));
  if (!isAllTruthy) return null;
  return (
    <>
      {typeof children === "function"
        ? children(when as ExcludeNullishFromObject<T>)
        : children}
    </>
  );
}

// 使用示例
<OnlyObject when={{ value1, value2, value3 }}>
  {({ value1, value2, value3 }) => (
    <MyComponent value1={value1} value2={value2} value3={value3} />
  )}
</OnlyObject>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 02:15:03