Reputation: 1016
I have a server side data loader that retrieves a user's ID from a data model, then checks that the user ID actually exists here:
export const loader = async ({ request, params }: LoaderArgs) => {
const REQUESTED_USER = await GetUserById(Number(params.id))
if (!REQUESTED_USER) {
/**
* If the provided url params user ID does not exist, we will handle it here
*/
return redirectWithError({
request,
message: `User ID: ${params.id} was not found; please enter a valid User ID`,
logMessage: `User ID: ${params.id} was not found; please enter a valid User ID`,
redirectTo: '/manager'
})
}
}
REQUESTED_USER returns:
const REQUESTED_USER: {
id: number;
company_name: string | null;
avatar: string | null;
brand: string | null;
email: string;
name: string | null;
favicon: string | null;
} | null
There is code after that block that does some data manipulation, then returns the data in a typed JSON response:
if (GET_SELECTED_SERVICES) {
sma = unwrap_sma[0]
edr = unwrap_edr[0]
cma = unwrap_cma[0]
vms = unwrap_vms[0]
}
return typedjson({
sma,
vms,
cma,
edr,
user
})
After which I am passing it to a component in React on the client side:
export const ReadUser = ({ }) => {
const LOADER = useTypedLoaderData<typeof loader>();
const [CSRF] = useCSRF()
return (
<main className="flex w-full">
<Form method="post" className="flex w-full">
<input className="hidden" name={'csrf'} value={CSRF} type="text" readOnly />
<Profile SMA={LOADER.sma} EDR={[]} VMS={[]} CMA={[]} />
</Form>
</main>
)
}
However, the attributes on the Profile
component are throwing this error:
Property 'sma' does not exist on type 'TypedResponse<never> | TypedJsonResponse<{ sma: TOptions[]; vms: TOptions[]; cma: TOptions[]; edr: TOptions[]; user: { id: number; company_name: string | null; ... 4 more ...; favicon: string | null; }; }>'.
Property 'sma' does not exist on type 'TypedResponse<never>'.ts(2339)
I have determined it is because of the initial REQUESTED_USER
guard in the server-side loader
function, whereby the LOADER
response is never fulfilled. I assume? this is due to Typescript not understanding the fulfillment of the request, but not 100% on that (if someone could elucidate on that).
Otherwise, how do I go about fixing this?
The type of the LOADER
const in ReadUser
component is:
const LOADER: TypedResponse<never> | TypedJsonResponse<{
sma: TOptions[];
vms: TOptions[];
cma: TOptions[];
edr: TOptions[];
user: {
id: number;
company_name: string | null;
... 4 more ...;
favicon: string | null;
};
}>
I did try to change the !REQUESTED_USER
argument to REQUESTED_USER === null
and that did not change anything
Upvotes: 0
Views: 1410
Reputation: 36936
I assume your loader can return types A = {x:1}
and B = {y:2}
, that results in union A | B
type for typeof loader
. If you try to access LOADER.x
ts will complain because LOADER
can be of type B
and there is no property x
on it, same the other way around.
As types are inferred correctly by what you actually return and there is no pretty way to discriminate union for or case, you can only assign type manually useTypedLoaderData() as A
or throw redirect that will remove first return type from union and seems also work in remix - throw redirect('/somewhere')
Upvotes: 1