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

如何创建支持TypeScript类型守卫is的React条件渲染组件?

实现带TypeScript类型守卫的RenderIfLoaded条件渲染组件

需求背景

现有React组件中,通过useState定义了User | undefined类型的user状态,当前用user &&的方式做条件渲染。想要封装一个RenderIfLoaded组件替代手动的存在性判断,同时让TypeScript自动识别组件内部的user对象已定义,无需额外写类型断言,利用TypeScript的is类型守卫实现。

实现步骤

1. 定义基础类型

先确保User类型已声明:

type User = {
  firstName: string;
  // 可根据需求添加其他用户属性
};

2. 编写RenderIfLoaded组件

首先写一个通用的类型守卫函数,用来判断值是否为非undefined、非null:

function isDefined<T>(value: T | undefined | null): value is T {
  return value !== undefined && value !== null;
}

接着定义组件的Props类型(用泛型适配任意对象类型),并实现组件逻辑:

import React from 'react';

type RenderIfLoadedProps<T> = {
  object: T | undefined | null;
  // 将children设计为接收已定义对象的函数,让TypeScript自动识别类型
  children: (obj: T) => React.ReactNode;
};

const RenderIfLoaded = <T,>({ object, children }: RenderIfLoadedProps<T>) => {
  // 未加载时返回null或自定义加载提示
  if (!isDefined(object)) {
    return null;
    // 可选:return <div>加载中...</div>;
  }
  // 此时object已被类型守卫收窄为T类型,安全传递给子组件
  return <>{children(object)}</>;
};

3. 在App组件中使用

const App: React.FC = () => {
  const [user, setUser] = React.useState<User | undefined>(undefined);

  React.useEffect(() => {
    // 模拟异步获取用户数据
    setTimeout(() => {
      setUser({ firstName: "John" });
    }, 2000);
  }, []);

  return (
    <div>
      <RenderIfLoaded object={user}>
        {/* 此处的user参数已被TypeScript识别为User类型,无需额外判断 */}
        {(user) => <div>Welcome {user.firstName}</div>}
      </RenderIfLoaded>
    </div>
  );
};

关键说明

  • 类型守卫isDefined会在组件内部完成存在性检查,TypeScript会自动根据这个检查收窄object的类型。
  • 把children设计为函数的形式,确保在子内容中使用的对象一定是已定义的,彻底消除undefined类型的报错。
  • 如果需要在加载状态展示提示,直接修改组件中!isDefined(object)的返回值即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 08:34:57