Skip to content

Commit

Permalink
fix(types): type result for throwOnError responses
Browse files Browse the repository at this point in the history
When using throwOnError(), the response type is now more strictly typed:
- Data is guaranteed to be non-null
- Error field is removed from response type
- Response type is controlled by generic ThrowOnError boolean parameter

Fixes #563
  • Loading branch information
avallete committed Jan 7, 2025
1 parent 09083ea commit c142420
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 8 deletions.
46 changes: 39 additions & 7 deletions src/PostgrestBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
// @ts-ignore
import nodeFetch from '@supabase/node-fetch'

import type { Fetch, PostgrestSingleResponse } from './types'
import type { Fetch } from './types'
import PostgrestError from './PostgrestError'

export default abstract class PostgrestBuilder<Result>
implements PromiseLike<PostgrestSingleResponse<Result>>
export default abstract class PostgrestBuilder<Result, ThrowOnError extends boolean = false>
implements
PromiseLike<
ThrowOnError extends true
? { data: Result; count: number | null; status: number; statusText: string }
: {
data: Result | null
error: PostgrestError | null
count: number | null
status: number
statusText: string
}
>
{
protected method: 'GET' | 'HEAD' | 'POST' | 'PATCH' | 'DELETE'
protected url: URL
Expand Down Expand Up @@ -42,9 +53,9 @@ export default abstract class PostgrestBuilder<Result>
*
* {@link https://github.com/supabase/supabase-js/issues/92}
*/
throwOnError(): this {
throwOnError(): PostgrestBuilder<Result, true> {
this.shouldThrowOnError = true
return this
return this as PostgrestBuilder<Result, true>
}

/**
Expand All @@ -56,9 +67,30 @@ export default abstract class PostgrestBuilder<Result>
return this
}

then<TResult1 = PostgrestSingleResponse<Result>, TResult2 = never>(
then<
TResult1 = ThrowOnError extends true
? { data: Result; count: number | null; status: number; statusText: string }
: {
data: Result | null
error: PostgrestError | null
count: number | null
status: number
statusText: string
},
TResult2 = never
>(
onfulfilled?:
| ((value: PostgrestSingleResponse<Result>) => TResult1 | PromiseLike<TResult1>)
| ((
value: ThrowOnError extends true
? { data: Result; count: number | null; status: number; statusText: string }
: {
data: Result | null
error: PostgrestError | null
count: number | null
status: number
statusText: string
}
) => TResult1 | PromiseLike<TResult1>)
| undefined
| null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
Expand Down
45 changes: 44 additions & 1 deletion test/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TypeEqual } from 'ts-expect'
import { expectError, expectType } from 'tsd'
import { PostgrestClient } from '../src/index'
import { PostgrestClient, PostgrestError } from '../src/index'
import { Prettify } from '../src/types'
import { Database, Json } from './types'

Expand Down Expand Up @@ -211,3 +212,45 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
expectType<typeof x>(y)
expectType<typeof x>(z)
}

// Should have nullable data and error field
{
const result = await postgrest.from('users').select('username, messages(id, message)').limit(1)
let expected:
| {
username: string
messages: {
id: number
message: string | null
}[]
}[]
| null
const { data } = result
const { error } = result
expectType<TypeEqual<typeof data, typeof expected>>(true)
let err: PostgrestError | null
expectType<TypeEqual<typeof error, typeof err>>(true)
}

// Should have non nullable data and no error fields if throwOnError is added
{
const result = await postgrest
.from('users')
.select('username, messages(id, message)')
.limit(1)
.throwOnError()
const { data } = result
// @ts-expect-error error property does not exist when using throwOnError()
const { error } = result
let expected:
| {
username: string
messages: {
id: number
message: string | null
}[]
}[]
expectType<TypeEqual<typeof data, typeof expected>>(true)
// just here so our variable isn't unused
error
}

0 comments on commit c142420

Please sign in to comment.