-
-
Notifications
You must be signed in to change notification settings - Fork 162
Improved typings #279
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
Improved typings #279
Conversation
ef2d5ee
to
4f9635b
Compare
src/PostgrestFilterBuilder.ts
Outdated
@@ -60,8 +67,8 @@ export default class PostgrestFilterBuilder<T> extends PostgrestTransformBuilder | |||
* @param column The column to filter on. | |||
* @param value The value to filter with. | |||
*/ | |||
eq(column: keyof T, value: T[keyof T]): this { | |||
this.url.searchParams.append(`${column}`, `eq.${value}`) | |||
eq<ColumnName extends string & keyof Table>(column: ColumnName, value: Table[ColumnName]): this { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking super cool @soedirgo!
Just wondering if there are plans to make this ColumnName
type even more helpful?
I see you're now allowing all strings plus suggesting the keys of the table – is it also possible to suggest the keys for embedded tables when the user provides the type?
type KeysOf<T, Key extends keyof T = keyof T> = Key extends string
? T[Key] extends (infer U)[]
? `${Key}.${KeysOf<U>}`
: T[Key] extends Record<string, any>
? `${Key}.${KeysOf<T[Key]>}`
: Key
: never;
(not thoroughly tested!)
Is this in scope for these changes? Or are we not going to allow users to provide nested types and have them as unknowns? (haven't dived into this deeply, so not fully informed sorry!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation in https://github.com/bnjmnt4n/supabase-client/blob/a1bd9d86fc04ffe9fd5172667644755d96456e29/src/postgrest/PostgrestFilterBuilder.ts#L39 actually does this, but I wanted to keep this simple and fall back to unknown
for now.
I noticed that it's not falling back to unknown
though - will update the PR. Thanks for noticing!
Hey @soedirgo! That repo was actually largely very experimental, and I didn't fully manage to integrate it into a usable Supabase client yet, so this is pretty exciting! On the other hand, while experimenting with that, I did have some notes:
|
@bnjmnt4n I agree, after implementing this I concluded that using template strings for the But I do think that this approach is a good local maximum at least - I'm thinking of not changing the API too much right now (there are other breaking changes in separate PRs alongside this one) - so the plan is to implement the typed array approach in the next major version.
Yup, I'm currently working on the typegen - which can be run using the Supabase CLI - to complement this PR. (Note that the typing changes here are incompatible with the OpenAPI-based typings.) It'll be based on https://github.com/supabase/postgres-meta, so we can get pretty much any info we want from the database, though I decided to put it off for now since even with FK info determining cardinality is still nontrivial (I probably need to look into how PostgREST does it). |
b192307
to
628be73
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
🎉 This PR is included in version 1.0.0-next.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
BREAKING CHANGE: Rework typings.
Closes #172, closes #217.
The current typings DX is not great. The way users supply types is through
.from<T>()
which needs to be done on each call. What ends up happening most of the time is users would leave theT
which defaults toany
, because this is the path of least resistance.Another sticking point is the
T
above also becomes the query result type, even though you can e.g. specify only certain columns.This change intends to alleviate the above by 1) accepting type definitions at the constructor, and 2) parsing
.select()
query to infer the result type.As an example, using the type definitions in
test/types.ts
:postgrest-js/test/types.ts
Lines 1 to 124 in 92beedd
We can use it like:
Most of the hard work in
.select()
query parsing is done by @bnjmnt4n in https://github.com/bnjmnt4n/postgrest-query. Here we're only implementing a subset of it because certain things are tricky to do properly, e.g.:::
)->
,->>
)members(id)
)members.id
)Embedded tables in
.select()
is especially tricky because it requires relation cardinality information, which can be calculated using FK information in the DB. e.g. for.from('orgs').select('members(*)')
orgs -> members
can be 1-to-many somembers
would be an array, but for the opposite i.e..from('members').select('orgs(*)')
members
would beobject | null
. Right now all embedded tables are typed asunknown
.