cli icon indicating copy to clipboard operation
cli copied to clipboard

"Computed field" is included in generated TypeScript type

Open gushecht opened this issue 1 year ago • 1 comments

Describe the bug Our database includes what are referred to in the PostgREST documentation as computed fields. These are Postgres functions on table types

When reviewing the output of running npx supabase gen types typescript, we are seeing that alongside the actual columns of a table, the computed fields are listed

To Reproduce Steps to reproduce the behavior:

  1. Ensure that you have a table in your database with a function on that table, e.g. run the following statements from the PostgREST documentation against your local Supabase database
CREATE TABLE people (
  first_name text
, last_name  text
, job        text
);

-- a computed field that combines data from two columns
CREATE FUNCTION full_name(people)
RETURNS text AS $$
  SELECT $1.first_name || ' ' || $1.last_name;
$$ LANGUAGE SQL;
  1. Generate TypeScript types by running npx supabase gen types typescript --local
  2. Observe that the Row for the people table indicates that there is a full_name property, for example
export type Database = {
  public: {
    Tables: {
      people: {
        Row: {
          first_name: string | null
          job: string | null
          last_name: string | null
          full_name: string | null
        }
        Insert: {
          first_name?: string | null
          job?: string | null
          last_name?: string | null
        }
        Update: {
          first_name?: string | null
          job?: string | null
          last_name?: string | null
        }
        Relationships: []
      }
    }
    Functions: {
      full_name: {
        Args: {
          "": unknown
        }
        Returns: string
      }
    }
  }
}

Expected behavior I'm curious if others think that this behavior is desirable. For us, this has been a problem because the generated types lead TypeScript to indicate that the computed fields exist on a row selected from the database. This led us to write some code that passed ts-lint, but caused an unexpected bug at runtime

For example, if one were to initialize the Supabase client with these generated types and then run

const { data, error } = await supabase.from("people").select("*");

the returned data would not include full_name, but TypeScript would think that data.full_name is either string | null. Instead, to have full_name one needs to explicitly include it by running

const { data, error } = await supabase.from("people").select("*, full_name");

System information Rerun the failing command with --create-ticket flag.

  • Ticket ID: N/A as there is not a failing command
  • Version of OS: MacOS 14.5
  • Version of CLI: 1.172.2
  • Version of Docker: Docker version 20.10.23, build 7155243
  • Versions of services:
  ─────────────────────────┼──────────────────────┼────────────
    supabase/postgres      │ 15.1.0.95            │ 15.1.0.95
    supabase/gotrue        │ v2.151.0             │ v2.152.1
    postgrest/postgrest    │ v10.2.0              │ v10.2.0
    supabase/realtime      │ v2.28.32             │ -
    supabase/storage-api   │ v1.2.1               │ v1.2.1
    supabase/edge-runtime  │ v1.53.3              │ -
    supabase/studio        │ 20240422-5cf8f30     │ -
    supabase/postgres-meta │ v0.80.0              │ -
    supabase/logflare      │ 1.4.0                │ -
    bitnami/pgbouncer      │ 1.20.1-debian-11-r39 │ -
    darthsim/imgproxy      │ v3.8.0               │ -

gushecht avatar Jun 07 '24 05:06 gushecht