Weboldal keresés

svelte - Typescript hiba SvelteKit és Supabase adatlekérdezés közben (A 'null' típus nem rendelhető az 'ArrayLike' típushoz)


Van egy SvelteKit projektem, amely a supabase-szal autentikál. Ehhez a cikkhez használtam ezt az útmutatót. Az autentikáció és az adatok lekérése eddig jól működik. Valójában az alkalmazás maga szempontjából minden a vártnak megfelelően működik. Csak egy csúnya Typescript hibát kapok, amelytől nem tudok megszabadulni.

A fájlban lévő adatokat töltöm be:

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

És a megfelelő svelte fájl annak megjelenítéséhez:

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

Most ezek azok a hibák, amiket kapok:

'pl' is of type 'unknown'.

És

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

De, ahogy mondtam, a weboldalon minden pontosan a vártnak megfelelően jelenik meg, és nincs más hibám, úgy tűnik, a Typescript egyszerűen nincs elégedve. Ami különös, hogy a data.user.email dolog egyáltalán nem dob hibát.

A Supabase által automatikusan generált típusok így néznek ki:

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

És úgy tűnik, hogy helyesen kerülnek levezetésre:

Az Intellisense ezt mutatja.

És ez az én app.d.ts fájlom:

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 {}
    }
}

Amikor az hibát kerestem, ezt találtam: https://github.com/sveltejs/language-tools/issues/732, és beszélnek valami hibáról a Typescript-ben, de én teljesen kezdő vagyok a Typescript-ben, szóval fogalmam sincs, hogy ez kapcsolódik-e vagy mi folyik ott.

Azt vártam, hogy a SvelteKit/Typescript a #each ciklusban is kikövetkezteti a típusokat a "data.playlist"-ből a sémám alapján, ugyanúgy, ahogy a script címkén belül teszi. Nem vagyok biztos benne, miért okoz ez nekem problémát. Köszönöm, hogy elolvastad!

Válasz #1

Úgy tűnik, hogy a supabase API esetleg visszaadhat null-t a data tulajdonságnál. Nem vagyok biztos benne, hogy ennek van értelme, amikor egy objektumok listáját választjuk, de ha a típus így jelzi, szükséged van egy ellenőrzésre vagy nem-null állításra.

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

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