SupabaseS
Supabase5mo ago
Boris

TypeScript: insert()/update()/upsert() argument type too permissive

Hello Supabase devs and community,

I'm dealing with an issue related to the TypeScript types of the mutation methods of the supabase-js client. Specifically, I'm finding that I can call these functions with keys that don't correspond to table columns and I won't get a type error, only a runtime error.

For example:

Consider a table "todos". Now imagine that the generated "update" type for "todos" (i.e. Database["public"]["Tables"]["todos"]["update"]), based on the table schema, is;
{
  id?: string;
  description?: string;
  completed?: boolean;
 }


Now the consider the following db client call:
await supabase.from("todos")
      .update({
        completed: true,
        some_random_key: "foo" // this is _not_ a known column of "todos"
      })
      .eq("id", "someTodoId");


Expectation: runtime error and compile-time error (i.e. TypeScript complains that some_random_key does not exist on Database["public"]["Tables"]["todos"]["update"])

Reality: Indeed, a runtime error, but no type error.

Was this a conscious choice? Was it a compromise due to technical constraints? Is it a bug? It has bitten me multiple times – the last of which was when I dropped a column – let's call it dropped_column – from a table and regenerated the TypeScript types, but because of the lack of compile error, I failed to remove dropped_column from one of my update calls and caused errors in production.

P.S. Let this not be conflated with the broader issue of TypeScript accepting objects with "excess" keys. For example, the following is known (albeit funky) TypeScript behavior:

function someFunc(params: { foo: string }) { /* do something */}

const someParams = { foo: "foo", bar: "bar"};
someFunc(someParams); // NO error expected!
someFunc({ foo: "foo", bar: "bar"}) // error expected!


So: inlined "excess" keys do normally trigger a TS error, and in my case, the excess key was indeed inlined, so why no error?
Was this page helpful?