Общий TypeScript для управления данными Supabase

У меня есть этот «types.ts», который я использую для более эффективного использования типов, сгенерированных с помощью 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];

Проблема в том, что мне не удается выполнить эту работу с запросом, для которого необходимо соединение...

Код по-прежнему будет работать нормально, например

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

позволит мне получить доступ к event.name, а также к event.table1.name, но IDE сообщает мне (очевидно), что «Свойство 'table1' не существует для типа»

я думал, что может быть что-то вроде

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

это сработало бы, но мне следует делать это для каждого случая SELECT с соединением, и это было бы ужасно... Если возможно, я бы хотел иметь что-то более общее, которое можно было бы адаптировать к большинству случаев.

Спасибо за любую помощь и простите меня за мой английский!

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
1
136
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В Supabase есть инструмент для генерации типов (supabase-type-generator)

Сначала сгенерируйте типы

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

И тогда супабаза может предоставить тип любого запроса следующим образом:

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

Спасибо @EmandM, я добавил дополнительную информацию о своей проблеме... Я не знаю, правильно ли я все делаю, я новичок в StackOverflow...

Maffio 23.05.2024 11:17

Спасибо за вашу помощь, я хотел бы попросить вас еще об одной вещи, чтобы правильно настроить мой конкретный случай:

На данный момент я разделил код на три файла:

(Таблица «events» на самом деле называется «eventi», а «table1» — «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;
        }
      });
}

-Моя домашняя страница (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>Ops, qualcosa è andato storto!</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

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;

Любые советы приветствуются, поскольку в начале моего проекта я также могу изменить структуру и логику, сейчас я выбрал этот, потому что, просматривая различные уроки, я нашел этот, и он показался мне изящным.

Другие вопросы по теме

Возникла проблема при оценке проекта «:react-native-firebase_app». Слишком поздно задавать пространство имен. Он уже прочитан для настройки этого проекта
Как мне изменить цвет кнопки при нажатии в React Native?
Нужно ли мне опубликовать приложение Facebook, чтобы запустить в производство мое собственное приложение React, использующее вход в Facebook?
Как мне подключить серверную часть проекта React Native Amplify к моему интерфейсу, размещенному в мобильных магазинах?
Ошибка: [auth/missing-client-identifier] В этом запросе отсутствует действительный идентификатор приложения, проверки целостности Play и проверки reCAPTCHA не увенчались успехом
Экспо зависло: экран «Добро пожаловать на Экспо»
Команда обновления eas выдает ошибку: ожидается, что экземпляр сервера Metro будет иметь открытые частные функции
Как запустить выставочный проект?
Как перейти с экрана вкладок на экран стека в React Native
Не удалось применить плагин com.facebook.react.rootproject