TypeScript - returned typed from query should reflect query filter
Opened this issue ยท 2 comments
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
Using query filters like .not("<column>", "is", null); does not produce types that correctly represents the returned data.
To Reproduce
Create a table posts
create table "public"."posts" (
"id" bigint generated by default as identity not null,
"content" text not null,
"published_at" date
);Generate types from the database schema.
supabase gen types typescript --local --schema public > functions/_shared/supabase.gen.ts
Write some TypeScript code to fetch posts.
import { createClient } from "@supabase/supabase-js";
import { Database } from "../_shared/supabase.gen";
const getPublishedPosts = async () => {
const supabase = createClient<Database>("supabaseUrl", "supabaseAnonKey");
const result = await supabase
.from("posts")
.select("*")
.not("published", "is", null);
if (result.error) {
throw result.error;
}
const data = result.data;
};Expected behavior
data should be of type
const data: {
content: string;
id: number;
published_at: string; // ๐ string, not string | null
}[]since we filtered published_at on NOT NULL in the query.
Actual behavior
data is of type
const data: {
content: string;
id: number;
published_at: string | null;
}[]System information
supabase --version: 2.23.4
node --version: v22.15.0
"devDependencies": {
"typescript": "5.8.3",
"@supabase/supabase-js": "2.49.8"
},
Types generated using the supabase CLI, are as per the schema of the table.
The create table DDL specified in the issue has "published_at" date. By default, postgres columns are nullable, unless you specify not null. With published_at as nullable, the type generated would be string | null.
since we filtered published_at on NOT NULL in the query.
Specifying not("published", "is", null) in the query does not change the type of the data returned. The data type for published_at would still be string | null as per the generated types for the table.
Edit: ORMs return the types from the schema. Parsing the query to identify if a type should be different is unnecessary overhead, and also opens up various other cases to be handled (casting for example).
I understand the technical aspect of it, I just think that it is a bad developer experience.
When writing .not("published", "is", null) all returned rows have non-null values for published_at, right? I believe the TypeScript typing system should reflect that.