In SvelteKit, I have a structure like this:
/accounts/[id]/+layout.server.svelte
/accounts/[id]/+layout.svelte
/accounts/[id]/view/+page.svelte
/accounts/[id]/edit/+page.svelte
/accounts/[id]/delete/+page.svelte
In the load()
function in +layout.server.svelte
I return the account with the given id, or null
if no account with the given id exists. I.e., the return type is:
{
account: Account | null
}
In +layout.svelte
, I only show the nested route if an account with the given id exists:
{#if data.account}
<slot />
{:else}
<p>No account with the given id exists!</>
{/if}
But in all the nested +page.svelte
files, the type of the data
props is still:
{
account: Account | null
}
But given the {#if}
check I have in +layout.svelte
, I know that account
will never be null
in the +page.svelte
files. Everything works great, but TypeScript complains that account
can be null
each time I use it in the +page.svelte
files, and that makes it very hard to read the code and see any potential real error.
What is the best/simplest workaround for this?
In SvelteKit, I have a structure like this:
/accounts/[id]/+layout.server.svelte
/accounts/[id]/+layout.svelte
/accounts/[id]/view/+page.svelte
/accounts/[id]/edit/+page.svelte
/accounts/[id]/delete/+page.svelte
In the load()
function in +layout.server.svelte
I return the account with the given id, or null
if no account with the given id exists. I.e., the return type is:
{
account: Account | null
}
In +layout.svelte
, I only show the nested route if an account with the given id exists:
{#if data.account}
<slot />
{:else}
<p>No account with the given id exists!</>
{/if}
But in all the nested +page.svelte
files, the type of the data
props is still:
{
account: Account | null
}
But given the {#if}
check I have in +layout.svelte
, I know that account
will never be null
in the +page.svelte
files. Everything works great, but TypeScript complains that account
can be null
each time I use it in the +page.svelte
files, and that makes it very hard to read the code and see any potential real error.
What is the best/simplest workaround for this?
Share Improve this question asked Nov 20, 2024 at 9:58 Peppe L-GPeppe L-G 8,3602 gold badges29 silver badges55 bronze badges1 Answer
Reset to default 1I would try to use +error
pages for that instead.
I.e. if the account is not found, use the error
function to cause an exception that will show the error page, that way the data can be non-nullable.
// in load
if (account == null)
error(404, { message: 'No account with the given id exists!' });
Note that if you throw errors in a layout's load function, the +error.svelte
from the directory above will be shown, unfortunately. So you need an /accounts/+error.svelte
page to handle this.
<!-- src/routes/accounts/+error.svelte -->
<script lang="ts">
import { page } from '$app/stores';
</script>
<p>{$page.error?.message ?? 'Unknown error'}</p>
If [id]
is the only meaningful sub-route that should not be a problem, otherwise you might have to add some metadata to the error to differentiate them if the message alone is not enough, e.g.
// in load
const body = {
message: 'No account with the given id exists!',
type: 'account-not-found',
};
error(404, body);
<!-- +error.svelte -->
<script lang="ts">
import { page } from '$app/stores';
$: error = $page.error as { type: string, message: string } | null;
</script>
{#if error?.type == 'account-not-found'}
<!-- Specific error handling here -->
<p>{error.message}</p>
{:else}
<p>Unknown error</p>
{/if}