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

Type instantiation is excessively deep and possibly infinite #1354

Open
2 tasks done
florian-lefebvre opened this issue Jan 14, 2025 · 4 comments
Open
2 tasks done

Type instantiation is excessively deep and possibly infinite #1354

florian-lefebvre opened this issue Jan 14, 2025 · 4 comments
Labels
bug Something isn't working

Comments

@florian-lefebvre
Copy link

florian-lefebvre commented Jan 14, 2025

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

The improvements made to type-safety (see https://github.com/orgs/supabase/discussions/32677) can break with "too complex" types when overriding Database.

To Reproduce

  1. Take those 2 files
// database.ts
import type { MergeDeep } from "type-fest";
import type { Database as DatabaseGenerated } from "./database-generated.types";

type Custom = {
  version: number;
  events: Array<{
    type: string;
    [x: string]: any;
  }>;
};

export type Database = MergeDeep<
  DatabaseGenerated,
  {
    public: {
      Tables: {
        foo: {
          Row: {
            bar: Custom;
            baz: Custom;
          };
          Insert: {
            bar: Custom;
            baz: Custom;
          };
          Update: {
            bar?: Custom;
            baz?: Custom;
          };
        };
      };
    };
  }
>;
// database.generated.ts

export type Json =
  | string
  | number
  | boolean
  | null
  | { [key: string]: Json | undefined }
  | Json[]

export type Database = {
  public: {
    Tables: {
      foo: {
        Row: {
          created_at: string | null
          bar: Json
          id: string
          baz: Json
          game_id: string
          updated_at: string | null
          user_id: string | null
        }
        Insert: {
          created_at?: string | null
          bar: Json
          id?: string
          baz: Json
          game_id: string
          updated_at?: string | null
          user_id?: string | null
        }
        Update: {
          created_at?: string | null
          bar?: Json
          id?: string
          baz?: Json
          game_id?: string
          updated_at?: string | null
          user_id?: string | null
        }
      }
    }
    Views: {}
    Functions: {
    }
    Enums: {
    }
    CompositeTypes: {
      [_ in never]: never
    }
  }
}

type PublicSchema = Database[Extract<keyof Database, "public">]

export type Tables<
  PublicTableNameOrOptions extends
    | keyof (PublicSchema["Tables"] & PublicSchema["Views"])
    | { schema: keyof Database },
  TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
    ? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
        Database[PublicTableNameOrOptions["schema"]]["Views"])
    : never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
  ? (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
      Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends {
      Row: infer R
    }
    ? R
    : never
  : PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] &
        PublicSchema["Views"])
    ? (PublicSchema["Tables"] &
        PublicSchema["Views"])[PublicTableNameOrOptions] extends {
        Row: infer R
      }
      ? R
      : never
    : never

export type TablesInsert<
  PublicTableNameOrOptions extends
    | keyof PublicSchema["Tables"]
    | { schema: keyof Database },
  TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
    ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
    : never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
  ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
      Insert: infer I
    }
    ? I
    : never
  : PublicTableNameOrOptions extends keyof PublicSchema["Tables"]
    ? PublicSchema["Tables"][PublicTableNameOrOptions] extends {
        Insert: infer I
      }
      ? I
      : never
    : never

export type TablesUpdate<
  PublicTableNameOrOptions extends
    | keyof PublicSchema["Tables"]
    | { schema: keyof Database },
  TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
    ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
    : never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
  ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
      Update: infer U
    }
    ? U
    : never
  : PublicTableNameOrOptions extends keyof PublicSchema["Tables"]
    ? PublicSchema["Tables"][PublicTableNameOrOptions] extends {
        Update: infer U
      }
      ? U
      : never
    : never

export type Enums<
  PublicEnumNameOrOptions extends
    | keyof PublicSchema["Enums"]
    | { schema: keyof Database },
  EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database }
    ? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"]
    : never = never,
> = PublicEnumNameOrOptions extends { schema: keyof Database }
  ? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName]
  : PublicEnumNameOrOptions extends keyof PublicSchema["Enums"]
    ? PublicSchema["Enums"][PublicEnumNameOrOptions]
    : never

export type CompositeTypes<
  PublicCompositeTypeNameOrOptions extends
    | keyof PublicSchema["CompositeTypes"]
    | { schema: keyof Database },
  CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
    schema: keyof Database
  }
    ? keyof Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"]
    : never = never,
> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database }
  ? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName]
  : PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"]
    ? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions]
    : never
  1. Instantiate a supabase client
const client = createClient<Database>("", "")
  1. Use the client
const { data } = client
    .from("foo")
    .select("id, bar, baz")
    .eq("id", "...")
    .single()

const bar = {} as Custom
const baz = {} as Custom

client
    .from("foo")
    .update({
        bar,
        baz
    })
    .eq("id", data.id)
  1. TS reports an error: Type instantiation is excessively deep and possibly infinite

Expected behavior

This error should not occur

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  • OS: Linux
  • Version of supabase-js: 2.47.12
  • Version of Node.js: 20.18.0

Additional context

Add any other context about the problem here.

@florian-lefebvre florian-lefebvre added the bug Something isn't working label Jan 14, 2025
@jarvisworks
Copy link

I am also using MergeDeep and have this exact same issue after updating supabase-js from 2.47.10 to 2.47.14

avallete added a commit to supabase/postgrest-js that referenced this issue Jan 20, 2025
@avallete
Copy link
Member

avallete commented Jan 20, 2025

Hey there!

Thanks for reporting this and for the detailed steps to reproduce the issue. I managed to get the same error on my end, and you can check it out here: Reproduction Link.

It's interesting that this only happens when TypeScript is updated past version 4.5.5. I'll take a closer look and see what's up.

In the meantime, could be useful to know which version of Typescript you are running (you can see it by running npx tsc -v inside your project)

Thanks for your patience!

Edit: Interestingly enough, digging a bit, it seems that the issue is also related to MergeDeep, replacing directly the types within the Database definition get rid of the error.

@florian-lefebvre
Copy link
Author

Hi! I'm using ts 5.7.3. I'm not surprised it's caused by MergeDeep, it must makes types way more complex

@Eigilak
Copy link

Eigilak commented Jan 22, 2025

wuuuuhuuuuuuu

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

4 participants