svelte - Chyba TypeScriptu pri SvelteKit a načítavaní dát zo Supabase (Typ 'null' nie je priraditeľný k typu 'ArrayLike')


Mám nastavený projekt SvelteKit, ktorý sa autentifikuje pomocou Supabase. Na to som použil tento návod. Autentifikácia a získavanie dát zatiaľ funguje dobre. Vlastne, čo sa týka samotnej aplikácie, všetko funguje podľa očakávania. Len sa mi objavuje nepríjemná chyba v TypeScripte, ktorej sa nemôžem zbaviť.

Načítavam dáta v tomto súbore:

// <!-- 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
    };
};

A príslušný súbor svelte na jeho zobrazenie:

<!-- 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>

Teraz sú to chyby, ktoré dostávam:

'pl' is of type 'unknown'.

A

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>'.

Ale ako som povedal, na webovej stránke je všetko zobrazené presne tak, ako sa očakávalo, a nedostávam žiadne iné chyby, zdá sa len, že Typescript nie je spokojný. Čudné je aj to, že vec data.user.email nespôsobuje vôbec žiadne chyby.

Automaticky generované typy zo Supabase vyzerajú takto:

// $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
        }
...

A zdá sa, že sú správne odvodené:

Intellisense to zobrazuje.

A toto je môj 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 {}
    }
}

Pri hľadaní chyby som našiel toto: https://github.com/sveltejs/language-tools/issues/732 a hovoria o nejakej chybe v Typescripte, ale ja som úplný začiatočník v Typescripte, takže nemám tušenie, či je to s týmto spojené alebo čo sa tam deje.

Očakával som, že SvelteKit/TypeScript odvodí typy pre „data.playlist“ zo môjho schémy aj v rámci #each slučky, rovnako ako to robí v rámci tagu script. Nie som si istý, prečo mi to robí problémy. Ďakujem za prečítanie!

Odpoveď č. 1

Zdá sa, že API supabase môže potenciálne vrátiť null pre vlastnosť data. Nie som si však istý, či to dáva zmysel pri výbere zoznamu objektov, ale ak to typ hovorí, budete potrebovať ochranu alebo asertívne označenie, že hodnota nie je null.

const { data: playlist } = ...
if (playlist == null)
  throw ...; // or make it a `let` and assign an empty array? 

// or
return {
    user: session.user,
    playlist: playlist!,
};