Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript error on CRUD API functions with Supabase. Inferring from Supabase database types error? (Tables | Row) #582

Open
eybel opened this issue Dec 5, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@eybel
Copy link

eybel commented Dec 5, 2024

Hello I have been struggling with my API query functions where I created my CRUD operations and typed them using different options.

SUMMARY:
I have 4 entities (services, articles, pets and objects) I wanted to re-use my CRUD so I infer types (data returned types and paylods) from "database.types.ts" but I can't make it work. It always complains about either my "payload" or my "return data" type.

import { supabase } from "@/lib/supabaseClient";
import { Database } from "@/types/database.types";

type TableSchema<T extends keyof Database["public"]["Tables"]> = Database["public"]["Tables"][T];
type Row<T extends keyof Database["public"]["Tables"]> = TableSchema<T>["Row"];
type Insert<T extends keyof Database["public"]["Tables"]> = TableSchema<T>["Insert"];
type Update<T extends keyof Database["public"]["Tables"]> = TableSchema<T>["Update"];

export const crudFactory = <
  T extends keyof Database["public"]["Tables"]
>(
  tableName: T
) => ({
  fetchOne: async (id: number): Promise<Row<T>> => {
    const { data, error } = await supabase
      .from(tableName)
      .select("*")
      .eq("id", id)
      .single();

    if (error) throw new Error(error.message);

    return data as Row<T>;
  },

  fetchAll: async (): Promise<Row<T>[]> => {
    const { data, error } = await supabase.from(tableName).select("*");

    if (error) throw new Error(error.message);

    return data as Row<T>[];
  },

  create: async (payload: Insert<T>): Promise<Row<T>> => {
    const { data, error } = await supabase
      .from(tableName)
      .insert(payload)
      .select()
      .single();

    if (error || !data) throw new Error(error?.message || "Failed to create");

    return data as Row<T>;
  },

  update: async (id: number, payload: Update<T>): Promise<Row<T>> => {
    const { data, error } = await supabase
      .from(tableName)
      .update(payload)
      .eq("id", id)
      .select()
      .single();

    if (error || !data) throw new Error(error?.message || "Failed to update");

    return data as Row<T>;
  },

  delete: async (id: number): Promise<boolean> => {
    const { error } = await supabase.from(tableName).delete().eq("id", id);

    if (error) throw new Error(error.message);

    return true;
  },
});

### ERRORS :

  1. it complains about the data returned (can't infer):
  2. it complains about the payload (can't infer):

Conversion of type '{ article: { Row: { approved: boolean; area: string | null; category: string; condition: string | null; created_at: string; deleted_at: string | null; description: string | null; event_at: string | null; ... 6 more ...; title: string; }; Insert: { ...; }; Update: { ...; }; Relationships: []; }; ... 7 more ...; servi...' to type 'Row<T>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.

Whats the best way to infer types for these CRUD? I tried lots of combination, it complains every single time. I have tried several ways of doing it, cant make it work. Its not detecting this. I cant continue with my app at the moment.

The only way was to cast the data frist as unknown first then the right type, but that is not recommended since it defeats the purpose of using typescript.

### NOTE. the returned data is typed like this (<SelectQueryError... ?). Is this the problem? Is it coming from postgress?:

const data: SelectQueryError<string> | { [K in keyof {
    article: {
        Row: {
            approved: boolean;
            area: string | null;
            category: string;

........
@eybel eybel added the bug Something isn't working label Dec 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant