Skip to content

[Feature Request] - Option for nulls as undefined #244

Closed as not planned
Closed as not planned

Description

@prescience-data

Feature request - Option for nulls as undefined

Currently, all empty values returned by the API are set as null.

The difference between null and undefined for many (obviously not all) TypeScript devs is meaningless, leading many to drop the null type completely. (In current projects I go as far as enforcing the Microsoft no-new-null eslint rule for example.)

This isn't meant to trigger any debate over if that is "right or wrong", just that undeniably (and for whatever reasons) some developers have this particular preference for type simplification.

Describe the solution you'd like

a) A configuration option in the SupbaseClient that coerces all nulls to undefined.
b) A server-side option to send null values as undefined pre-flight. (edit: #244 (comment))

Describe alternatives you've considered

Presently I need to run each record through a recursive function to convert each null value and adjust the type shape accordingly.

Additional context

A specific case where this is especially problematic:

import { z } from "zod"

export const FooSchema = z.object({
  id: z.number().optional(),
  title: z.string(),
  color: z.string().optional().default("red")
})

const { data, error } = await supabase.from(`foos`).select(`id, title, color`).single()
if (data) { 
  const foo = FooSchema.parse(foo)
}
ZodError.ts:134 Uncaught (in promise) ZodError: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "null",
    "path": [
      "color"
    ],
    "message": "Expected string, received null"
  }
]

Normally this would convert an empty value for "color" to "red", however due to the fact that null !== undefined it fails.

Activity

  1. soedirgo commented on Aug 24, 2021

    @soedirgo
    Member

    +1, I realized after the fact that e.g. the TypeScript coding guidelines (caveat: read the title) uses only undefined as the bottom type and forbids null. There isn't much point in having 2 bottom types and I think we also use undefined in a few places.

    Rather than making it a configuration though, I'd prefer to apply this for supabase-js v2 instead. What do you think?

  2. prescience-data commented on Aug 25, 2021

    @prescience-data
    Author

    That sounds awesome. 😍
    After thinking and reading about this a bit more, I retract my "option b (server-side)" as I could see this mode may easily break other non-TypeScript languages.
    To "steel-man" the other side, there is an argument to be made when dealing with database data that a Prisma team member has made here, however, I think so long as the transformation only applies to the JS library I personally think the benefits (sindresorhus, Crockford) of simplification outweigh the cons.

    (ps: I always love reading that warning on the TS guidelines page, they must be so sick of this debate by now 🤣)

  3. danielpox commented on Jul 24, 2022

    @danielpox

    One thing to note regarding JSON is that undefined does not exist, whereas null is a value.

    For instance, JSON.parse('undefined') throws an error, but JSON.parse(null) returns null.

    When stringifying a JavaScript object into JSON, all key/value-pairs with the value of undefined will be skipped, whereas pairs with the value of null will be included.

    Here's an example: JSON.stringify({ empty: null, hide: undefined }) returns '{"empty":null}'.
    This is very handy when you want to send back as little data as possible to the client, by removing all fields "without value".

    null is considered a "value", as it represents "nothing", "empty" or "void", but undefined means it doesn't exist at all.

    So, when retrieving data via Supabase (or Postgrest), we may get a whole lot of fields being null, when we may want them to be excluded altogether, depending on the use case.

    We could of course use some recursive function to do this manually, but it would be nice if it would be baked in to the library via an options parameter.

    So, it's not just a question about TypeScript or schema validations, because it returns a completely different dataset in JSON depending on whether it's null or undefined!

  4. soedirgo commented on Jul 25, 2022

    @soedirgo
    Member

    @danielpox thanks for the input! Yes, in supabase/postgrest-js#278 we decided to adopt the Prisma team's stance on this. We do use undefined instead of null for function args etc., but not for Postgres values.

  5. NiklasPor commented on Dec 5, 2023

    @NiklasPor

    Hi all, while I also would love this feature from TypeScript / client side, it would also be awesome if the payload sent by the backend could be stripped of null values. Rows / queries which return a lot of nulls often include way more key/value pairs (where the value is null) then they need to.

  6. antoniormrzz commented on Feb 8, 2024

    @antoniormrzz

    With each passing day, I'm coming back to this issue, wondering if this is the reason that zod in trpc output is failing. Am I correct to assume that supabase now returns undefined for null? and that the typegen in cli doesn't account for this by generating return types as well? While the response may be typed, I am using supabase-to-zod and then using the zod result in trpc output validation.

  7. NiklasPor commented on Feb 8, 2024

    @NiklasPor

    With each passing day, I'm coming back to this issue, wondering if this is the reason that zod in trpc output is failing. Am I correct to assume that supabase now returns undefined for null? and that the typegen in cli doesn't account for this by generating return types as well? While the response may be typed, I am using supabase-to-zod and then using the zod result in trpc output validation.

    The author describes the implementation as "hacky" and the last release was a year ago. I'd be careful in building on it in general.

    But I think the idea of it is superb.

  8. antoniormrzz commented on Feb 8, 2024

    @antoniormrzz

    The author describes the implementation as "hacky" and the last release was a year ago. I'd be careful in building on it in general.

    But I think the idea of it is superb.

    The idea of anything zod is repulsive to me. Unfortunately I was not behind that decision. zod was put in to use tRPC, and then supabase-to-zod to generate zod validators. I am a NestJS type of gentleman myself. Class-validator rules.

  9. veloware commented on Sep 11, 2024

    @veloware

    Also running into this, and its an absolute pain. Im building forms that have optional fields, and in typescript, that pretty simple with -

    type FormData = {
       foo?: string;
    }
    

    but constantly running into supabase problems with it complaining that I cannot assign string | undefined to string | null

    I think this would be relatively easy to coerce using something like -

    undefined ?? null    // null
    

    but would be awesome if this could be a config in the lib as mentioned above :)

  10. soedirgo commented on Sep 9, 2025

    @soedirgo
    Member

    @veloware as mentioned above undefined and null have different semantics. For your specific case if it's an .insert(), { foo: undefined } means the default value for foo will be used, which can be different from null.

  11. soedirgo commented on Sep 9, 2025

    @soedirgo
    Member

    Closing this as we're keeping the null as value, undefined as non-value semantics for now

  12. added a commit that references this issue on Oct 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions