let's say I have this component that Wrap other component in 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 }
)}
</>
);
};
Now I would like to use this like this
const { data } = useMyQuery<X>(); // data is type X | undefined
<LoadWrapper defined={data}>
<AnotherComponent data={data} /> // here data is type X | undefined but I would like only X since the check has been done on the wrapper.
</LoadWrapper>
Is there a way to achieve this ?
CodePudding user response:
I can't think of a nice way while keeping the current structure the same - but a simple tweak could do it. Note that the LoadWrapper does nothing but render the children after loading, and does nothing but render other elements (that don't use the children) otherwise. So, it's not so much a wrapper, so much as a conditional element. Consider moving the condition outside, and then TypeScript will be able to understand when data
is or isn't defined.
export const LoadWrapper = () => (
<div className="flex flex-1 items-center justify-center">
<div className={className}>
<Spinner />
</div>
</div>
);
const { data } = useMyQuery<X>();
return data
? <AnotherComponent data={data} />
: <LoadWrapper />;
Or, if it's surrounded by other JSX, you could do something like
<div>{
data
? <AnotherComponent data={data} />
: <LoadWrapper />
}</div>
CodePudding user response:
Although the previous response is a good one and, in my opinion, has a better structure, if you want to stay with de same component structure, it may work with a type cast over data
variable, like:
<LoadWrapper defined={data}>
<AnotherComponent data={data as X} /> // or "data as unknown as X"
</LoadWrapper>