SupabaseJS v2 Typescript

I am attempting to create a React Query provider that wraps the Supabase v2 JS client. I love the type improvements of the new version of the Supabase client so I definitely want to keep them in tact. However, by wrapping the client query in a react query function, I am having trouble typing how the return types of the client, or getting the client types inferred. Basically I am just looking to have this function use the same types as the client.
The types in the v2 JS are a bit complex for me to try to duplicate as the return type of this function, so I wanted to see if anyone had any suggestions on how I may get this done. useReactQuery does take a generic which will be the return type of the fetched data. However, I'm a bit lost on what that return type should be as a lot of it looks like its inferred from the table name in the standalone v2 client.
type GeneratedQuery = PostgrestFilterBuilder<any, any> & { _table?: string };
type QueryCreator = (supabase: SupabaseClient<Database>) => PostgrestFilterBuilder<any, any> & { _table?: string };

function useQuery(queryCreator: QueryCreator, options?: UseQueryOptions & { queryKey?: string | unknown[] }) {
const query = queryCreator(client);

const execute = (query: GeneratedQuery) =>
new Promise<any>(async (resolve, reject) => {
const { data, error } = await query;
if (data) {
resolve(data);
} else {
reject(error);
}
});

return useReactQuery(options?.queryKey ?? [query._table], () => execute(query), options);
}
type GeneratedQuery = PostgrestFilterBuilder<any, any> & { _table?: string };
type QueryCreator = (supabase: SupabaseClient<Database>) => PostgrestFilterBuilder<any, any> & { _table?: string };

function useQuery(queryCreator: QueryCreator, options?: UseQueryOptions & { queryKey?: string | unknown[] }) {
const query = queryCreator(client);

const execute = (query: GeneratedQuery) =>
new Promise<any>(async (resolve, reject) => {
const { data, error } = await query;
if (data) {
resolve(data);
} else {
reject(error);
}
});

return useReactQuery(options?.queryKey ?? [query._table], () => execute(query), options);
}
When I call useQuery in a component (eg) Id like the return type of the client query to go to categories
const categories = useQuery((supabase) => supabase.from("categories" *this table name autocompleted fine).select("name, id"));

categories.{no types on the return value of categories :/}
const categories = useQuery((supabase) => supabase.from("categories" *this table name autocompleted fine).select("name, id"));

categories.{no types on the return value of categories :/}
This has sort of stretched my knowledge of Typescript thin and any help is appreciated!
6 Replies
drewbie
drewbieOP3y ago
Am I able to bump this?
NΛRCISO
NΛRCISO3y ago
I'm looking for a similar snippet too. @drewbie can you provide a bit more of the code like the imports and the "client" variable? Actually PostgrestFilterBuilder seems to not be exported from @NativeBPM/supabase-js
drewbie
drewbieOP3y ago
@NΛRCISO - I asked a question about it here - https://github.com/supabase/supabase/discussions/9530
GitHub
Supabase JS v2 Types + React Query · Discussion #9530 · supabase/su...
I&#39;m loving the new type improvements with the v2 JS library ❤️. I am trying to integrate them with React Query in addition to the React Context examples that have been provided by Supabase....
drewbie
drewbieOP3y ago
The tough part is what generics do you pass to the PostgrestFitlerBuilder since the js library infers the return based on the methods and arguments you give to the client Will be extra sweet to have end to end type safety for react query, queries and mutations plus the Supabase JS types Just using React Query directly in your components will work just fine, but it means youve got to explicitly declare your query keys every time you query/mutate something and just doesnt isolate your fetching logic to a single source. Id really like to figure out how to get it in a context provider so I can pass the Supabase client + React Query function around all over the app and have it be consistent
nickbrinser
nickbrinser3y ago
Trying to sort this out as well for a query builder. I had this working with a simple generic with PostgrestFilterBuilder in v1.
drewbie
drewbieOP3y ago
@nickbrinser - You can still pass in a generic to useQuery if that's what you mean? What stinks is that generic isn't actually accurate for what the client returns 😕 which means you need to really hold its hand when passing the generic which is unfortunate.

Did you find this page helpful?