Problem
I'm having trouble narrowing types with Tanstack Svelte Query. I am migrating my app from React to Svelte.
My query queryGetMyPageCollection()
returns either an object PageCollection
or false
. PageCollection
has a getPageByPath()
method that returns a Page
object or undefined
.
This is where the problem occurs:
{#if $query.data && $query.data.getPageByPath(data.slug)}<p>Hooray! We found your page!</p><DisplayPage page={$query.data.getPageByPath(data.slug)} />
I am checking $query.data
, which is false
or the PageCollection
object, and, if the object exists, calling getPageByPath()
against the query string to see if we can load a Page
object. If the page object exists, then I display the page in the <DisplayPage>
component.
This code works but TypeScript complains about the <DisplayPage>
line:
Error: Type 'Page | undefined' is not assignable to type 'Page'.
Type 'undefined' is not assignable to type 'Page'. (ts)
However, I know that the getPageByPath()
call for the <DisplayPage>
component will not be undefined because I checked it in the #if
statement.
Similar code works in React, so I'm guessing that in Svelte, TypeScript is not setting the type for the method call in the <DisplayPage>
component based on the #if
statement directly above it.
Question
How do I code this so that TypeScript does not produce an error? Please do not answer "set @tsignore
"; I want to know how to actually solve this the TypeScript/Svelte way.
Full component code
<script lang="ts"> export let data; const query = createQuery({ queryKey: queryKeyUsePages, queryFn: async () => queryGetMyPageCollection() });</script><div> {#if $query.isLoading}<p>Loading...</p> {:else if $query.isError}<p>Error: {$query.error.message}</p> {:else if $query.isSuccess}<h1>Here is the page</h1> {#if $query.data && $query.data.getPageByPath(data.slug)}<p>Hooray! We found your page!</p><DisplayPage page={$query.data.getPageByPath(data.slug)} /> {:else}<p>On no! We didn't find your page.</p> {#if $query.data}<p>Available paths:</p><ul> {#each $query.data.pages as page}<li><a href="/{page.path}">{page.title}</a></li> {/each}</ul> {/if} {/if} {/if}</div>