如何创建支持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
相关产品推荐
相关产品推荐

