supabase / postgrest-js

Isomorphic JavaScript client for PostgREST.

Home Page:https://supabase.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Integrate Prettify to get rid of intersection types

TomasHubelbauer opened this issue · comments

Bug report

Hi, this is an improvement suggestion and I have first opened a documentation thread for this but it has not seen any activity since I opened it last week so I figure I'd reopen it here to give it a chance to get some attention.

Describe the bug

When using Postgrest .select('a,b,c') we get an intersection type back: { a: type; } & { b: type } & { c: type }.

To Reproduce

  1. Check out https://github.com/supabase/postgrest-js
  2. Add this code snippet to index.test-d.ts:
    {
      const { data, error } = await postgrest
        .from('users')
        .select('username,data,status')
      if (error) {
        throw new Error(error.message)
      }
      expectType<{ username: string; data: Json; status: "ONLINE" | "OFFLINE" | null; }[]>(data)
    }
  3. Hover over data to see its real type
  4. Observe the inferred type is an intersection type

Expected behavior

I am hoping we can incorporate this to make the type non-intersected:

type Prettify<T> = { [K in keyof T]: T[K] } & {};

Credit goes to https://twitter.com/mattpocockuk/status/1622730173446557697.

Screenshots

Currently we get this inferred type when hovering over data from select:

{
    username: string;
} & {
    data: Json;
} & {
    status: "ONLINE" | "OFFLINE" | null;
}

With Prettify hovering over the select response data we'll see this inferred type:

{
    username: string;
    data: Json;
    status: "ONLINE" | "OFFLINE" | null;
}

Hey, this looks great! Would definitely want this in the lib :)

Amazingly, I managed to write all this text and yet forgot to include a link to the original discussion thread :D
supabase/supabase#12292

I already tried implementing this but ran into a problem. Citing myself from that thread:

I am hoping Prettify could be somehow integrated into the postgrest-js types so I looked at src/types.ts. I clicked through data and error to PostgrestResponseSuccess and PostgrestResponseFailure.

I cannot just extend PostgrestResponseSuccess like so because the response is potentially an array:>

+ type Prettify<T> = { [K in keyof T]: T[K] } & {};
  export interface PostgrestResponseSuccess<T> extends PostgrestResponseBase {
    error: null
-   data: T
+   data: Prettify<T>
    count: number | null
  }

I tried extending PostgrestSingleResponse<T> instead:

  type Prettify<T> = { [K in keyof T]: T[K] } & {};
  export type PostgrestSingleResponse<T> =
-   | PostgrestResponseSuccess<T>
+   | PostgrestResponseSuccess<Prettify<T>>
    | PostgrestResponseFailure

This didn't work, the inferred type was still intersected. I also tried wrapping T in PostgrestMaybeSingleResponse and PostgrestResponse but the result was the same.

I see these response types are only exported from the package but not really used internally.

Where else should I look to integrate Prettify? I realize that select is not the only endpoint returning possibly interesected types, DB functions will probably do it, too? How can I enumerate all of the possible places Prettify could be added to?

Can you help me out with where to put Prettify?

I see, so I guess it only works on one layer.

Can you try this diff?

diff --git a/src/select-query-parser.ts b/src/select-query-parser.ts
index dc90ec7..5f8c5a7 100644
--- a/src/select-query-parser.ts
+++ b/src/select-query-parser.ts
@@ -1,6 +1,6 @@
 // Credits to @bnjmnt4n (https://www.npmjs.com/package/postgrest-query)
 
-import { GenericSchema } from './types'
+import { GenericSchema, Prettify } from './types'
 
 type Whitespace = ' ' | '\n' | '\t'
 
@@ -342,7 +342,7 @@ type GetResultHelper<
   ? GetResultHelper<Schema, Row, [], ConstructFieldDefinition<Schema, Row, R> & Acc>
   : Fields extends [infer R, ...infer Rest]
   ? GetResultHelper<Schema, Row, Rest, ConstructFieldDefinition<Schema, Row, R> & Acc>
-  : Acc
+  : Prettify<Acc>
 
 /**
  * Constructs a type definition for an object based on a given PostgREST query.
diff --git a/src/types.ts b/src/types.ts
index f9bbf66..f2464d3 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -69,3 +69,5 @@ export type GenericSchema = {
   Views: Record<string, GenericView>
   Functions: Record<string, GenericFunction>
 }
+
+export type Prettify<T> = { [K in keyof T]: T[K] } & {}

It works!!!

image

Very epic, PR incoming!

:tada: This issue has been resolved in version 1.4.1 :tada:

The release is available on:

Your semantic-release bot 📦🚀