Error encountered when using Typescript with SvelteKit and Supabase data retrieval (Cannot assign type 'null' to type 'ArrayLike<unknown>')

My SvelteKit project is configured to authenticate with supabase. I followed this guide for the setup. Authentication and data fetching are working smoothly so far. However, I'm encountering a persistent Typescript error that I can't seem to resolve.

The data fetching occurs 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 here's the corresponding svelte file used to display the data:


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

The errors I'm facing include:

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

Despite these errors, the webpage displays everything as expected without any other issues. It appears that Typescript is just not satisfied. It's interesting to note that accessing data.user.email does not trigger any errors.

The autogenerated types from supabase schema 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
        }
...

Intellisense seems to infer these types correctly:Link to screenshot

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

I came across this discussion regarding a possible bug in Typescript: Link to GitHub issue. As a beginner in Typescript, I'm unsure if this is related to my situation or what exactly is causing the problem.

I was expecting SvelteKit/Typescript to automatically infer the types for "data.playlist" based on my schema within the #each loop, similar to how it's handled within the script tag. The fact that I'm encountering difficulties is puzzling. Thanks for taking the time to read through!

Answer №1

It appears that the supabase API may return a value of null for the data property. It seems odd when dealing with a list of objects, but if the data type allows it, you may need to implement a guard or use a not-null assertion.

const { data: playlist } = ...
if (playlist == null)
  throw ...; // Alternatively, consider assigning an empty array instead? 

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Challenges encountered while using TypeScript to implement the CSS breakpoint mixin

I attempted to replicate the breakpoint mixin functionality described at using TypeScript, but I am having trouble correctly typing the function. import { css } from 'styled-components'; import { breakpoints } from './_variables'; exp ...

The CSS "mask" property is experiencing compatibility issues on Google Chrome

Hey there! I've recently developed a unique progress bar component in React that showcases a stunning gradient background. This effect is achieved by utilizing the CSS mask property. While everything runs smoothly on Firefox, I'm facing a slight ...

Eslint for Typescript in Vue is throwing an error with a message "Unexpected token, expecting ','. Make sure to

Whenever I attempted to utilize vue's type assertion, I kept encountering this eslint error. To illustrate, consider the following snippet: data: function () { return { sellerIdToListings: {} as any, // 'as' Unexpected to ...

Utilizing Angular Services to Share Events and Reusing Components Multiple Times on a Page

My unique custom table is made up of multiple components, each emitting events using a shared service called TableEvent. These events are subscribed to by a class named TableTemplate, which facilitates communication among the different components of the ta ...

Angular 12: How to detect when a browser tab is closing and implement a confirmation dialog with MatDialog

I have a scenario where I am checking if the browser tab is closed using the code below. It currently works with windows dialog, but I would like to incorporate MatDialog for confirmation instead. @HostListener('window:beforeunload', ['$eve ...

Demystifying the Mechanics of RxJS Subscriptions during an HTTP Request

export class VendorHttpService { result = '0'; constructor(private http: HttpClient, private global: GlobalService) { } getProfileStatus(uid: String): string { this.http.get(this.global.getUrl()+"/vendor/profile-status/"+uid) ...

Tips for creating a page component in Next.js using props?

I've encountered an issue while trying to properly annotate the parameters of the Home function component. My initial attempt was to use: { events }: { events: Event[] }, but TypeScript is throwing an error, stating that Property 'events' do ...

Color changes on mat-calendar when hovering

Is it possible to change the hover color of the Mat-calender element? I managed to do so using this CSS code: .mat-calendar-body-cell-content:hover { background-color:#something } The issue is that when hovering the cursor in the corner of the cell, the ...

Troubleshooting: Unable to filter reducers in Redux when using the remove

I'm attempting to eliminate an element from an array using the filter method in this manner: removeDisplate: (state, action: PayloadAction<string>) => { console.log(action.payload); state.map((item) => { console.log(item.name); } ...

Angular dynamic array binding binds to multiple elements rather than just one

In my code, I am working with an array object structured as follows: let myArray=[ { "id":"100", "child1":[ {"id":"xx","Array":[]}, {"id":"yy","Array":[]}, {"id":"zz","Array":[]} ] }, { "id":"200", "child1":[ {"id":"xx","Array ...

Displaying Well-Formatted XML in Angular2 Using Typescript

After receiving this XML string from the server: <find-item-command xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" find-method="Criteria" item-class="com" only-id="false" xsi:schemaLocation=""> <criteria> <criterion> <descripto ...

Utilize the object's ID to filter and display data based on specified criteria

I retrieved an array of objects from a database and am seeking to narrow down the results based on specific criteria. For instance, I want to display results only if a user's id matches the page's correct id. TS - async getResultsForId() { ...

Updating a label dynamically in Angular

QUESTION: Is there a way to dynamically change the text of a label based on a certain condition? Specifically, I want the label to be blank when I'm on a specific route in my App. CURRENT APPROACH: <RadSideDrawer allowEdgeSwipe=&quo ...

Using LitElement: What is the best way to call functions when the Template is defined as a const?

When the template is defined in a separate file, it's not possible to call a function in the component. However, if the template is defined directly as returning rendered HTML with this.func, it works. How can one call a function when the template is ...

Having trouble with Angular 2's Output/emit() function not functioning properly

Struggling to understand why I am unable to send or receive some data. The toggleNavigation() function is triggering, but unsure if the .emit() method is actually functioning as intended. My end goal is to collapse and expand the navigation menu, but for ...

The Angular Tooltip feature is unable to interpret the characters "' '" or "' '"

Let me explain the scenario: I am receiving a list of objects from my back-end service, which I then break apart using ngFor and display accordingly. Each item in the list has an associated toolTip that provides additional information. The info for each i ...

Checking constructor arguments and code style issues

I need to ensure that the constructor parameter is validated correctly when an instance of a class is created. The parameter must be an object that contains exactly all the properties, with the appropriate types as specified in the class definition. If t ...

What is the procedure for linking the value (<p>John</p>) to the mat form field input so that it displays as "John"?

Can I apply innerHTML to the value received from the backend and connect it to the matInput? Is this a viable option? ...

Unit testing Angular components can often uncover errors that would otherwise go unnoticed in production. One common

I need assistance writing a simple test in Angular using Shallow render. In my HTML template, I am utilizing the Async pipe to display an observable. However, I keep encountering the following error: Error: InvalidPipeArgument: '() => this.referenc ...

Creating a custom extended version of Angular2 Http does not automatically provide injection of services

I'm struggling to understand this issue. I've created a custom class that extends Angular's Http class. import { Injectable } from '@angular/core'; { Http, ConnectionBackend, RequestOptions, RequestOptionsArgs, ...