React中如何让编译器认定包装组件内的值不会为undefined?
问题描述
我在React中编写了一个加载状态包装组件,代码如下:
interface LoadWrapperProps { defined?: boolean; children: React.ReactNode | React.ReactNode[]; } export const LoadWrapper = ({loading, children }: LoadWrapperProps) => { return ( <> {defined ? ( <div className="flex flex-1 items-center justify-center"> <div className={className}> <Spinner /> </div> </div> ) : ( { children } )} </> ); };
我希望按如下方式使用该组件:
const { data } = useMyQuery<X>(); // data 类型为 X | undefined <LoadWrapper defined={data}> <AnotherComponent data={data} /> // 此处data仍为X | undefined,但我希望仅为X,因为包装组件已做校验 </LoadWrapper>
请问是否有办法实现这一需求?
解决方案
当然可以实现,核心是通过将children定义为函数类型,结合TypeScript泛型传递经过类型断言后的有效值,同时修正原组件里的参数匹配错误(比如loading与defined不匹配、未定义className等问题)。
步骤1:重构组件的Props与实现
把children改为接收非空值的函数,用泛型约束传入值的类型:
import React from 'react'; import { Spinner } from './Spinner'; // 假设Spinner是你的加载组件 interface LoadWrapperProps<T> { // 泛型T代表传入值的类型,defined为T | undefined defined: T | undefined; // children是接收非空T值的函数,返回React节点 children: (value: T) => React.ReactNode; // 可选的加载状态容器类名 spinnerClassName?: string; } export const LoadWrapper = <T,>({ defined, children, spinnerClassName }: LoadWrapperProps<T>) => { // 根据需求调整非空判断逻辑,这里仅排除undefined if (defined === undefined) { return ( <div className="flex flex-1 items-center justify-center"> <div className={spinnerClassName}> <Spinner /> </div> </div> ); } // 值存在时,调用children函数并传入已确定非空的defined return <>{children(defined)}</>; };
步骤2:使用重构后的组件
此时data会被自动推断为非空的X类型:
const { data } = useMyQuery<X>(); <LoadWrapper defined={data}> {/* 这里的value已经是X类型,不再包含undefined */} {(value) => <AnotherComponent data={value} />} </LoadWrapper>
额外说明
- 原组件中
loading参数与判断逻辑里的defined不匹配,这里统一用defined控制加载状态显示; - 非空判断逻辑可按需调整,比如需要排除
null可改为defined == null; - 泛型
T会自动根据传入的defined值推断类型,无需手动指定,特殊场景除外。
内容的提问来源于stack exchange,提问作者Crocsx
相关产品推荐
相关产品推荐

