-
Notifications
You must be signed in to change notification settings - Fork 538
Description
Bug report
- I confirm this is a bug with Supabase, not with my own application.
- I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
When using the Supabase JavaScript client (supabase-js), mutation methods such as .update() allow passing object keys that don’t correspond to actual table columns. These invalid keys don’t trigger a TypeScript error, only a runtime error from the database.
This means TypeScript does not enforce strict column checks on Database["public"]["Tables"]["<table>"]["update"] types.
To Reproduce
- Create a table
todoswith the following columns:
id uuid primary key,
description text,
completed boolean- Generate the TypeScript types. The
Database["public"]["Tables"]["todos"]["update"]type will look like:
{
id?: string;
description?: string;
completed?: boolean;
}- Call the update function with an extra key that isn’t part of the table:
await supabase
.from("todos")
.update({
completed: true,
some_random_key: "foo", // ❌ not a real column
})
.eq("id", "someTodoId");- Observe that:
- At compile time: no TypeScript error
- At runtime: a database error is thrown
Expected behavior
I expected both:
- A runtime error from Postgres (which happens)
- A compile-time error from TypeScript (which does not happen)
This way, dropping or renaming a column would result in a TS error when the code references it. Currently, errors slip through to production if not caught in runtime testing.
System information
- Version of supabase-js:
2.52.0
Additional context
I acknowledge that TS has a well-known “excess property checks” quirk (though I don't think this issue is an example of that). Here's what I mean:
function someFunc(params: { foo: string }) {}
someFunc({ foo: "foo", bar: "bar" }) // ✅ error expected, and indeed TS errors
const someParams = { foo: "foo", bar: "bar"};
someFunc(someParams); // NO error expected!But with Supabase’s update() type, inlined excess keys do not error. I’m curious if this is a conscious design decision, a TypeScript technical constraint, or an actual bug in the type generation.