TypeScript made specifically for organizing and handling data within Supabase

I created a file named "types.ts" to efficiently utilize types generated with Supabase CLI.

import { Database } from './database.types';

export type Tables<T extends keyof Database['public']['Tables']> =
  Database['public']['Tables'][T]['Row'];

export type Enums<T extends keyof Database['public']['Enums']> =
  Database['public']['Enums'][T];

However, I am struggling to make it work with a query that requires a join operation.

The code functions correctly in simple cases such as

type EventListItemProps = {
  event: Tables\<"events"\>
}

This allows me to access properties like event.name and event.table1.name. Yet, the IDE indicates that "Property 'table1' does not exist on type."

I considered adding something like the following for each SELECT statement with a join:

type EventListItemProps = {
  event: Tables\<"events"\> & {
    table1: Tables\<"table1\"\>;
  };
}

However, having to do this for every join case would be tedious. If possible, I am looking for a more generic solution that can handle most situations.

Thank you for any assistance, and please overlook any errors in my English!

Answer №1

If you're using Supabase, they offer a convenient tool that can generate types for you (supabase-type-generator)

To begin, start by generating the types with the following commands:

npx supabase gen types typescript --project-id "$PROJECT_REF" --schema public > types/supabase.ts
// or if working locally
npx supabase gen types typescript --local > types/supabase.ts

Once that's done, you can easily retrieve the type of any query with Supabase like this:

const queryResult = supabase.from('events').select(`
  event_id,
  table1 (
    field1
  )
`)

type EventListItemProps = QueryData<typeof queryResult>

const { data, error } = await queryResult
if (error) throw error

const eventListItem: EventListItemProps = data

Answer №2

Thank you for your assistance. I have a question regarding the correct configuration of my specific scenario:

Currently, I have divided the code into three separate files:

(Note: The table named "events" is actually referred to as "eventi" and "table1" is called "locali")

-api/events/index.ts

import { supabase } from '@/lib/supabase';
import { useQuery } from '@tanstack/react-query';

export const useEventList = () => {
    return useQuery({
        queryKey: ["eventi"],
        queryFn : async()=>{

          const {data, error} = await supabase
            .from("eventi")
            .select(`*, locale:locali(*)`);

          if(error)
            throw new Error(error.message);
          return data;
        }
      });
}

-My Home page (app/events/index.tsx)

import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import EventListItem from "@/components/eventi/EventListItem";
import { useEventList } from '@/api/events';



export default function Home() {
  
  const{data: eventi, error, isLoading} = useEventList();
  
  if(isLoading){
    return <ActivityIndicator />
  }
  
  if(error){
    return <Text>Oops, something went wrong!</Text>
  }
  
  return (
    <View style={{ flex: 1 }}>
    <FlatList
    style={{flex:1}}
    data = {eventi}
    renderItem={({item}) => <EventListItem evento={item}/>}
    numColumns={1}
    contentContainerStyle={{gap:10, padding:10}}
    // columnWrapperStyle={{gap:10}}
    />
    </View>
  );
}

-EventListItem component

import { StyleSheet, View, Text, Pressable, Image, } from 'react-native';
import {Tables} from "@/types";
import { Link } from 'expo-router';
import { Colors } from '@/constants/Colors';

type EventListItemProps = {
    evento: Tables<"eventi"> & {
        locale: Tables<"locali">;
      };
}

const EventListItem = ({evento}: EventListItemProps) => {
    const dayjs = require('dayjs');
    const eventDate = dayjs(evento.dt_inizio).format("DD/MM");
    return(
        <Link href={`/eventi/${evento.id}`} asChild>
            <Pressable style={styles.card}>
                {/* <Image
                    source = {{uri: evento.img || "" }}
                /> */}
                <Text>{evento.nome}</Text>
                <Text>{evento.locale.nome}</Text>
                <Text>{eventDate}</Text>
            </Pressable>
        </Link>
    )
}

const styles = StyleSheet.create({
    card: {
        flex: 1,
        borderRadius: 7,
        paddingVertical: 5,
        paddingHorizontal: 8,
        backgroundColor: Colors.light.tabIconSelected,
    }
})

export default EventListItem;

Any suggestions or recommendations are appreciated. As I am in the initial stages of my project, I am open to changing the structure and approach. Currently, I opted for this setup after exploring various tutorials as it appeared organized and concise.

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

Iterate over the key-value pairs in a loop

How can I iterate through a key-value pair array? This is how I declare mine: products!: {[key: string] : ProductDTO}[]; Here's my loop: for (let product of this.products) { category.products.push((product as ProductDTO).serialize()); } However, ...

React: Unable to locate an index signature with a parameter of type 'string' on type N

While working with a React component, I encountered an issue when trying to access a property from my component state using a key. My editor showed the following warning: Element implicitly has an 'any' type because expression of type 'str ...

The specialized middleware in Next.js gets dispatched to the browser

Attempting to retrieve user information based on the current session, I created a small _middleware.ts file. In order to get the users' data, I imported a prisma (ORM) client. However, upon loading the page in the browser, an error message appeared: ...

Combining multiple arrays of objects using multiple keys with Angular 9 and Typescript

I have two JSON objects (displayed here with JSON.stringify(array of objects)) GPRows data is [ { "shopName":"Testing One", "state":"NSW", "yearMonth":"20203", "id& ...

Using the fs module in a React Native application

Currently, I am facing a challenge in importing TinyDB into an expo project. The issue lies with fs, as Expo does not support it due to its third-party file system nature. I attempted using react-native-fs as an alternative but I am unsure about how to pr ...

The array is not being spliced in the DOM, however, it is being spliced in the console - Ionic 2+/Angular

My scenario involves a dynamic array filled with items and values. The goal is to remove an item from the view list when a user clicks a button on that particular item. I'm struggling to identify why this functionality isn't working as expected. ...

The class-transformer malfunctioning: The transformation function is not being executed

I am facing an issue with implementing class-transformer in my codebase, despite using type-graphql and @typegoose/typegoose libraries. Below is the snippet of my code: Custom Decorator import { Transform } from 'class-transformer'; export func ...

Having trouble getting the useStep hook function to work with an onClick arrow function?

When the submit button is clicked, I want to trigger an alert if the text box is empty and move to the next page if there is input, using the next function. I can achieve one or the other separately, but when I try to combine them, only the checkInput() fu ...

Error encountered: The database is not found during the migration creation process in MikroORM

Attempting to create migrations with mikroORM has been a challenge as I am unable to generate the table itself. The error message indicating that the database "crm" does not exist leaves me puzzled about what steps I may have missed. Here is the code snip ...

Encountered a problem while setting up React app using npm

I've encountered an issue while trying to install a react app using npm. Even after downgrading my npm version to 3, I am still facing errors. My internet connection is strong as well. Thank you in advance for your assistance! https://i.stack.imgur ...

The system encountered an error: "__fbBatchedBridge" variable cannot be located

After initializing a new React Native project with `react-native init AwesomeProject`, I encountered the error 'ReferenceError: Can't find variable: __fbBatchedBridge (line 1 in the generated bundle)' when running the app using the default c ...

Can you explain the return value of array.find() in Typescript or Java script?

In my Typescript code, I have the following line: const addressFound: AddressPrimary = <AddressPrimary>(this.addressArray.find(addr => addr.id === id)); The AddressPrimary class contains various variables such as id: number, city: number, and oth ...

extracting the HTML content from JavaScript and saving it into a standalone file

update When I click a link, a popup opens and I see all this HTML. The smile method is called when I click the link, and we append HTML in that method so that we can see it when the popup is opened. I moved it to a separate file something.component.html, ...

Converting an array of form data into JSON using Angular and Typescript

When submitting a form using ng-submit in my Angular application, I receive an array of fields that I need to post to a RESTful web service. However, I'm unsure how to map and convert this data into the desired final object template within my Angular ...

Troubles encountered with ionic's usage of [innerHTML] within <ion-list>

Encountering an issue while using ionic 3 and angular 2 with styling a large HTML string using [innerHTML]. Strangely, the string gets cut off at the end of the screen instead of wrapping to the next line when placed within an ion-list tag. Any insights on ...

React Native: The state value is being interpreted as undefined

Within my Logitem component, I have implemented a Modal that is triggered when a Text element is clicked. The functionality of this part is functioning correctly, and I am successfully handling the click event. However, I am encountering an issue where t ...

Angular - finding an elegant solution for handling multiple HTTP requests

As a newcomer to Angular, I've been working on a project where I need to load various local .json files using http-requests. While my current approach works, I can't help but wonder if there's a more elegant solution. Currently, I load the ...

What is the process of importing types in TypeScript?

Here is the export I am working with: import * as jwt from 'jsonwebtoken'; ... export type MyJsonWebToken = typeof jwt; Next, when attempting to use it in my code: export class AuthService { constructor( @Inject(constants.JWT) private ...

Encountering a getStaticProps error while using Typescript with Next.js

I encountered an issue with the following code snippet: export const getStaticProps: GetStaticProps<HomeProps> = async () => { const firstCategory = 0; const { data }: AxiosResponse<MenuItem[]> = await axios.post( ...

Angular6 returns the result after subscribing to an HTTP POST request

Currently, I am in the process of learning angular and attempting to create a component that allows users to register through my web API. Within my component, the code on form submission looks like this: onSubmit(contactFormRef: NgForm) { const resu ...