supabase / postgrest-js

Isomorphic JavaScript client for PostgREST.
https://supabase.com
MIT License
962 stars 128 forks source link

ParserError "Unexpected input: .sum()" when using aggregate functions with TypeScript #523

Open stefan-girlich opened 3 months ago

stefan-girlich commented 3 months ago

Bug report

Describe the bug

When I use aggregate functions, the inferred TypeScript data type will always depict an error, requiring me to use casts to any.

To Reproduce

  const { data } = await supabase.from("things").select(`
    field.sum(),
    ...other_things(id, name, color)
  `);

The inferred type for data seen in my VS Code is: ParserError<"Unexpected input: .sum(),\n ...other_things(id, name, color)\n ">[] | null

Inference works fine when not using aggregate functions. Re-generating TS types via supabase gen types typescript does not fix the issue.

Expected behavior

Types should be inferred correctly without an error.

System information

encima commented 3 months ago

Moving this issue to Postgrest-js repo. Issue is similar to https://github.com/supabase/postgrest-js/issues/447 which was fixed recently

stefan-girlich commented 2 months ago

A brief update after upgrading supabase-js from 2.39.7 to 2.42.0:

Error in TypeScript type is now as following for the same original code:

const data: SelectQueryError<"Referencing missing column `sum`">[] | null

Using .count() instead of .sum() works as expected, but all other functions (.min(), .max(), .avg()) (src) still produce the error above.

@bnjmnt4n I just had a look into your fix for the similar issue with .count() (diff). Do you think it's sufficient to add sum, min, max, and avg in the same manner? Maybe there's also a way to reference the type AggregateFunctions (src) Update: I think I found a way; looking into it.

stefan-girlich commented 2 months ago

@bnjmnt4n I added test cases which currently fail at compile-time.

bnjmnt4n commented 2 months ago

@stefan-girlich thanks for providing the examples; I'm really busy now so I can probably look at them next week only.

stefan-girlich commented 4 weeks ago

In case it helps anyone, here's a generic way to override the faulty type:

import fail from '@/utils/fail'
import { createClient } from '@/utils/supabase/server'

type FixSupabaseAggregateType<
  T extends readonly any[] | null,
  K extends keyof R,
  R extends Record<K, any>,
> = Array<Omit<NonNullable<T>[number], K> & R>

export const fetchSomeData = async () => {
  const supabase = createClient()
  const { data, error } = await supabase
    .from('some_table')
    .select(
      `
        some_prop,
        other_table(aggregated_prop:nested_prop.sum())
    `
    )

  if (error) fail(error)

  type Result = FixSupabaseAggregateType<
    typeof data,
    'other_table',
    {
      other_table: { aggregated_prop: number }
    }
  >

  return data as unknown as Result
}

@bnjmnt4n Would you know if a fix is scheduled already? Thanks!