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

如何让TypeScript正确识别条件渲染组件的类型推断逻辑?

解决ConditionalRender组件的TypeScript类型推断问题

问题核心

自定义的ConditionalRender组件无法让TypeScript识别条件判断后的类型窄化逻辑,导致在编辑模式下访问data.id时,TypeScript仍认为data可能是无id属性的CreateModeValues类型;而直接使用{isEditMode && <p>{data.id}</p>}的写法,却能让TypeScript正确推断类型。

解决方案:用回调式children+泛型条件类型实现类型窄化

要让TypeScript正确关联condition和子元素的类型上下文,需要将ConditionalRender的children设计为回调函数,结合泛型条件类型约束回调的参数类型,从而实现和原生&&写法一致的类型推断效果。

1. 定义表单的两种数据类型

// 创建模式的数据类型(无id属性)
type CreateModeValues = {
  name: string;
};

// 编辑模式的数据类型(继承创建模式并添加id)
type EditModeValues = CreateModeValues & {
  id: string;
};

// 表单数据的联合类型
type FormValues = CreateModeValues | EditModeValues;

2. 实现支持类型推断的ConditionalRender组件

import React from 'react';

// 组件Props类型:根据condition的布尔值约束children的类型
type ConditionalRenderProps<T, Condition extends boolean> = {
  // 条件判断值,泛型捕获其布尔类型
  condition: Condition;
  // 需要根据条件窄化的数据
  data: T;
  // 当condition为true时,回调参数被约束为带id的EditModeValues类型
  children: Condition extends true 
    ? (narrowedData: Extract<T, { id: string }>) => React.ReactNode 
    : never;
};

export function ConditionalRender<T, Condition extends boolean>({
  condition,
  data,
  children,
}: ConditionalRenderProps<T, Condition>) {
  if (condition) {
    // 类型断言:确保condition为true时,data符合回调参数的类型
    return children(data as Extract<T, { id: string }>);
  }
  return null;
}

3. 使用示例

在表单组件中使用时,TypeScript会自动根据isEditMode的布尔值,推断回调函数内的editData为EditModeValues类型,访问id不会报错:

function Form({ isEditMode, data }: { isEditMode: boolean; data: FormValues }) {
  return (
    <div>
      <input value={data.name} onChange={() => {}} />
      
      {/* TypeScript能正确识别:isEditMode为true时,editData必有id属性 */}
      <ConditionalRender condition={isEditMode} data={data}>
        {(editData) => <p>当前编辑ID:{editData.id}</p>}
      </ConditionalRender>
    </div>
  );
}

原理说明

  • 泛型Condition extends boolean会捕获condition的具体布尔类型(true/false),让TypeScript能区分两种条件分支。
  • 回调式children替代直接的ReactNode,使得TypeScript可以根据condition的类型约束回调参数的类型,实现类型窄化。
  • Extract<T, { id: string }>从联合类型FormValues中提取出包含id属性的分支,确保回调参数的类型安全。

如果不需要传递data,仅单纯基于条件渲染,可简化组件:

type SimpleConditionalProps<Condition extends boolean> = {
  condition: Condition;
  children: Condition extends true ? () => React.ReactNode : never;
};

export function SimpleConditionalRender<Condition extends boolean>({
  condition,
  children,
}: SimpleConditionalProps<Condition>) {
  return condition ? children() : null;
}

// 使用方式
<SimpleConditionalRender condition={isEditMode}>
  {() => <p>仅编辑模式显示</p>}
</SimpleConditionalRender>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:03:21