supabase / postgrest-js

Isomorphic JavaScript client for PostgREST.
https://supabase.com
MIT License
965 stars 129 forks source link

Typescript - Fetched data is type is not being inferred correctly based on injected data types #407

Open mikeschneiderdotme opened 1 year ago

mikeschneiderdotme commented 1 year ago

Bug report

Describe the bug

When querying the database context in Typescript, the data returned is always of type any instead inferring the correct type from the injected database types. Previously, the correct types would be returned in the data object.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create a database context using type injection as documented here
  2. Using the context, query a table with a know injected type const { data, error } = supabaseClient.from('authors').select()
  3. Observe returned data object type

Expected behavior

The expected behavior, and what previously happened, is that the data object type would be correctly inferred as an Author[] object based on injected data types. Instead the data object is of type `any[]

Screenshots

image

System information

Frame1910 commented 1 year ago

I've got the exact same issue:

Screenshot 2023-03-28 at 10 02 13 am

I've noticed the various PostgrestBuilder objects aren't noticing the typings, however the supabase client object is:

Screenshot 2023-03-28 at 10 03 32 am

Oddly enough, if I specify the columns manually the types carry over fine, but not when using the wildcard *

Screenshot 2023-03-28 at 1 18 09 pm

Any insight would be greatly appreciated.

galaxyblur commented 7 months ago

Same here. Doesn't work with the Supabase docs' suggestions either.

const supabase = createClient<Database>(supabaseUrl, supabaseKey);

export function modelStoreFactory<T extends keyof Database['public']['Tables']>(tableName: string) {
  const tbl = supabase.from(tableName);

  type TRow = Database['public']['Tables'][T]['Row'];
  type TInsert = Database['public']['Tables'][T]['Insert'];

  async function insertItem(item: TInsert): Promise<TRow> {
    const result: PostgrestSingleResponse<TRow> = await tbl.insert(item).select();
  }
}

Result:

 1. Type 'PostgrestSingleResponse<any[]>' is not assignable to type 'PostgrestSingleResponse<TRow>'.
      Type 'PostgrestResponseSuccess<any[]>' is not assignable to type 'PostgrestSingleResponse<TRow>'.
        Type 'PostgrestResponseSuccess<any[]>' is not assignable to type 'PostgrestResponseSuccess<TRow>'.
          Type 'any[]' is not assignable to type 'TRow'.

Edit: The Supabase JS Client docs were not super clear on this, but I fixed the error in this case by using .limit(1).single() to return only one updated object, as I expected.