I have a SvelteKit project set up which authenticates with supabase. I used this guide for that. The authentication and data fetching works fine so far. Actually, in terms of the app itself, everything works as expected. I’m just getting a nasty Typescript error which I can’t get rid of.
I’m fetching the data in this file:
// <!-- routes/playlists/+page.ts -->
import type { PageLoad } from './$types';
import { redirect } from '@sveltejs/kit';
export const load: PageLoad = async ({ parent }) => {
const { supabase, session } = await parent();
if (!session) {
throw redirect(303, '/');
}
const { data: playlist } = await supabase.from('playlist').select('*');
return {
user: session.user,
playlist
};
};
And the corresponding svelte file to display it:
<!-- routes/playlists/+page.svelte -->
<script lang="ts">
import type { PageData } from './$types';
import { json } from '@sveltejs/kit';
export let data: PageData;
</script>
<main>
<div>{data.user.email}</div> <!-- This works fine! -->
<ul>
{#each data.playlist as pl} <!-- Typescript complains about this -->
<li>
{pl.spotify_uri} <!-- and this -->
</li>
{/each}
</ul>
</main>
Now these are the errors I’m getting:
'pl' is of type 'unknown'.
And
Argument of type '{ created_at: string; follower_count: number; last_auto_renewal: string; last_manual_renewal: string; playlist_id: number; spotify_uri: string; user_id: string | null; }[] | null'
is not assignable to parameter of type 'ArrayLike<unknown>'.
Type 'null' is not assignable to type 'ArrayLike<unknown>'.
But, as I said, on the webpage everything is displayed just as expected & I’m getting no other errors, it just seems that Typescript isn’t happy. What’s also weird is that the data.user.email thing throws no errors at all.
The auto-generated types from supabase look like this:
// $lib/supabase/schema.ts
export interface Database {
public: {
Tables: {
playlist: {
Row: {
created_at: string
follower_count: number
last_auto_renewal: string
last_manual_renewal: string
playlist_id: number
spotify_uri: string
user_id: string | null
}
...
And they seem to get inferred correctly:
And this is my app.d.ts:
import { SupabaseClient, Session } from '@supabase/supabase-js';
import { Database } from '$lib/supabase/schema';
declare global {
namespace App {
interface Locals {
supabase: SupabaseClient<Database>;
getSession(): Promise<Session | null>;
}
interface PageData {
session: Session | null;
}
// interface Error {}
// interface Platform {}
}
}
When searching for the error I found this: https://github.com/sveltejs/language-tools/issues/732 and they talk about some bug in Typescript, but I’m a total Typescript beginner so I have no idea if this is related or what’s going on there.
I expected SvelteKit/Typescript to infer the types for "data.playlist" from my schema within the #each loop as well, just like it’s doing within the script tag. Not sure why it’s giving me trouble. Thanks for reading!
Sounds like the supabase API can possibly return null
for the data
property. Not sure if that makes sense when selecting a list of objects, though, but if the type says so, you need a guard or not-null assertion.
const { data: playlist } = ...
if (playlist == null)
throw ...; // or make it a `let` and assign an empty array?
// or
return {
user: session.user,
playlist: playlist!,
};