英文:
Typescript error with SvelteKit and Supabase data fetching (Type 'null' is not assignable to type 'ArrayLike<unknown>')
问题
以下是您提供的代码的翻译部分:
// <!-- 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
    };
};
<!-- 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>
// $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
        }
      }
    }
  }
}
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 {}
	}
}
希望这能帮助您理解问题并找到解决方案。如果您需要进一步的帮助,请告诉我。
英文:
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!
答案1
得分: 0
听起来,supabase API 可能会在 data 属性上返回 null。虽然在选择对象列表时是否有意义还不确定,但如果类型指明如此,你需要添加一个保护或非空断言。
const { data: playlist } = ...
if (playlist == null)
  throw ...; // 或者将其声明为 `let` 并分配一个空数组?
// 或者
return {
    user: session.user,
    playlist: playlist!,
};
英文:
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!,
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论