-
Notifications
You must be signed in to change notification settings - Fork 402
Description
Context
I use the TS compiler option exactOptionalPropertyTypes: true
in my codebase (for general TS logic as well as Convex logic) to prevent a lot of footguns with missing attributes vs attributes with a value of undefined
, but it's incompatible with the dynamic types that Convex emits for schema with optional fields:
Repro
const schema = defineSchema({
users: defineTable({
stripeSubStatus: v.optional(v.string()),
}),
});
Convex emits stripeSubStatus?: string | undefined
, but at runtime a Convex ctx.db.query
would never return undefined
for a field, it would just omit it (conflicting with exactOptionalPropertyTypes
).
Convex patch operation type safety
With the exactOptionalPropertyTypes
flag on, TS properly prevents { foo: undefined }
unless I explicitly type it that way, which e.g. reduces accidental field drops for ctx.db.patch
operations.
My proposal
As a customer I can't force others to use exactOptionalPropertyTypes
, and other customers probably already rely on the current prop?: T | undefined
.
To maintain backward compatibility, Convex could add an opt-in type parameter on defineSchema
(similar to the existing StrictTableNameTypes extends boolean = true
), maybe StrictOptionalTypes extends boolean = false
, which would mean Convex emits the stricter prop?: T
instead.
Cc @thomasballinger since @ianmacartney mentioned Tom has been internally advocating for this for years.