---
number: 39773
slug: 39773-enhanced-type-inference-for-embedded-functions-computed-relationships
published: 2025-10-22
discussion: https://github.com/orgs/supabase/discussions/39773
labels:
  - javascript
page: https://supabase.com/changelog/39773-enhanced-type-inference-for-embedded-functions-computed-relationships
---

# Enhanced Type Inference for Embedded Functions (Computed Relationships)

With `@supabase/supabase-js@2.75.1` and a CLI version **> 2.53.1**, the type-generation and runtime support for embedded functions / computed relationships has been improved. The introspection now includes `SetofOptions` metadata via the [supabase/postgres-meta#971](https://linear.app/supabase/review/feattypegen-add-functions-setof-type-introspection-df06251fc67d), and the client library types in `supabase-js` now provide stronger type inference *and* compile-time errors for invalid function usage.

### 🔍 What’s new

* Functions returning `SETOF` or table types are now correctly inferred as embedded relationships (arrays) when used in `.select()` queries (computed relationships). Supported via `SetofOptions` from introspection.
  **note**: If you define a function in Postgres with `RETURNS SETOF … ROWS 1`, the tool-chain (introspection + type generation) will infer this as a *single object* instead of an array.
* TypeScript errors at call-site when you attempt to call a function with wrong or conflicting parameters. For example:

  ```ts
  const res = await supabase.rpc('postgrest_unresolvable_function', { a: 'test' });
  // Error: Could not choose the best candidate function between: public.postgrest_unresolvable_function(a => integer), public.postgrest_unresolvable_function(a => text).
  ```

  This kind of error helps you catch ambiguous overloads that the introspection cannot decide between.
* Additional error cases like:

  ```typescript
  const res = await supabase.rpc('blurb_message', {});
  // Error: Searched for the function public.blurb_message with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache.
  ```

  This corresponds to underlying PostgREST error codes `PGRST202` / `PGRST203`.

**Important caveats:**

Nullable embed relationships by default: When you embed a function (computed relationship) in a `.select()` query, the generated type will treat the function result as possibly `null`, since it may not return any rows.

You **can override** the nullability globally using a DeepMerge override when generating types using the CLI. Example:

```ts
import { MergeDeep } from 'type-fest'
import { Database as DatabaseGenerated } from './database-generated.types'

export type Database = MergeDeep<
  DatabaseGenerated,
  {
    public: {
      Functions: {
        my_function: {
          SetofOptions: {
            isNotNullable: true
          }
        }
      }
    }
  }
>
```

This approach mimics [defining custom JSON types](https://supabase.com/docs/guides/api/rest/generating-types#defining-custom-json-types) via MergeDeep.

However, when a function has **multiple overloads** or multiple `SetofOptions` variants (for example one overload returns from `someTable` → `someOtherTable`, another returns `someTable2` → `someOtherTable`), a global override may become ambiguous:

```ts
function_name:
  | { ..., SetofOptions: { from: 'someTable', to: 'someOtherTable' } }
  | { ..., SetofOptions: { from: 'someTable2', to: 'someOtherTable' } }
```

In such cases, the recommendation is to use the `!inner` hint in the query itself so the inference knows the result won’t be null:

```ts
client
  .from('table')
  .select('field1, computed_relationship!inner(id)')
// Inferred type:
// { field1: string, computed_relationship: { id: string } }
// rather than default:
// { field1: string, computed_relationship: { id: string } | null }
```

### ✅ What you should do

1. Upgrade to `@supabase/supabase-js@2.75.1` (or higher)
2. Ensure you are using the CLI at version **> 2.53.1** so that `SetofOptions` metadata is correctly included in the generated types.
3. Regenerate your types (e.g., `npx supabase gen types typescript …`) after introspection so that functions with `SETOF` return types are captured with the proper metadata.

### 🔗 References

* [PostgREST docs — Computed Relationships](https://docs.postgrest.org/en/stable/references/api/resource_embedding.html#computed-relationships)
* [supabase/supabase-js#1632](https://github.com/supabase/supabase-js/pull/1632)
* [supabase/postgres-meta#971](https://github.com/supabase/postgres-meta/pull/971)
* [Defining custom JSON types (type override docs)](https://supabase.com/docs/guides/api/rest/generating-types#defining-custom-json-types)
