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

Integrate Prettify to get rid of intersection types #398

Closed
TomasHubelbauer opened this issue Feb 16, 2023 · 5 comments · Fixed by #399
Closed

Integrate Prettify to get rid of intersection types #398

TomasHubelbauer opened this issue Feb 16, 2023 · 5 comments · Fixed by #399
Labels
bug Something isn't working released

Comments

@TomasHubelbauer
Copy link
Contributor

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;
}
@TomasHubelbauer TomasHubelbauer added the bug Something isn't working label Feb 16, 2023
@soedirgo
Copy link
Member

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

@TomasHubelbauer
Copy link
Contributor Author

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?

@soedirgo
Copy link
Member

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] } & {}

@TomasHubelbauer
Copy link
Contributor Author

It works!!!

image

Very epic, PR incoming!

soedirgo added a commit that referenced this issue Feb 21, 2023
* Prettify intersected types when selecting multiple columns

Resolves #398

* update type test

---------

Co-authored-by: Bobbie Soedirgo <[email protected]>
@github-actions
Copy link

🎉 This issue has been resolved in version 1.4.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants