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;
}
{
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");
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!
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?
0 Replies
No replies yetBe the first to reply to this messageJoin

Did you find this page helpful?