Skip to content

fix(schema): drop constructor defaults when deriving update schemas#814

Open
MindfulLearner wants to merge 11 commits into
mainfrom
feat-omit-default-removal
Open

fix(schema): drop constructor defaults when deriving update schemas#814
MindfulLearner wants to merge 11 commits into
mainfrom
feat-omit-default-removal

Conversation

@MindfulLearner

@MindfulLearner MindfulLearner commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

const Person = Schema.Struct({
  name: Schema.String,
  age: Schema.Finite.pipe(Schema.propertySignature, Schema.withConstructorDefault(() => 0))
})

const UpdatePerson = Schema.Struct({
  name: Schema.optional(Schema.String),
  age: Schema.Finite.pipe(Schema.optional, Schema.withConstructorDefault(() => 0))
})

// current
UpdatePerson.make({ name: "test" }) // => { name: "test", age: 0 }

// desired
UpdatePerson.make({ name: "test" }) // => { name: "test" }

Any field carrying withConstructorDefault gets auto-filled by .make() when omitted, by design. Struct.omit/pick just makes it easy to inherit one from an entity schema without noticing; writing the field by hand on an Update schema hits the same behavior. Clients call .make() implicitly on .mutate(), so the default silently overwrites the value the caller left untouched.

Fix

const UpdatePerson = Schema.Struct(
  Struct.map(Struct.omit(Person.fields, [] as const), S.dropConstructorDefault)
)

UpdatePerson.make({ name: "test" }) // => { name: "test" }
  • dropConstructorDefault: a Struct.Lambda that removes a field's constructor default. Replaces the earlier combined omitConstructorDefaults helper.
  • makeExactOptional now drops constructor defaults automatically.

Out of scope (follow-up candidates, not blocking this PR)

  • shortcut helper combining omit + map(dropConstructorDefault) in one call
  • dropping decoding defaults (only constructor defaults are handled here)

Related: https://github.com/macs-holding/configurator/pull/851
Discussion: https://discord.com/channels/1083767712431480922/1521940676416241745

@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@814

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@814

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@814

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@814

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@814

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@814

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@814

commit: 1f18526

@MindfulLearner MindfulLearner self-assigned this Jul 2, 2026
@patroza

patroza commented Jul 2, 2026

Copy link
Copy Markdown
Member

Inheriting the behaviors of fields is desired. In what case are you considering this undesirable or a "bug"?
This pr / issue lacks motivation.

If you need a tool to strip withConstructorDefault then i would suggest to make a helper that just does that so you can simply mapFields(flow(Struct.omit(..), stripConstructorDefaults))

@MindfulLearner MindfulLearner changed the title feat(): added implementation, api test and story test, and added comment for Struct.omit jsdoc fix(schema): drop constructor defaults when deriving update schemas Jul 6, 2026
Comment thread packages/effect-app/src/Schema/ext.ts
Comment thread packages/effect-app/src/Schema/ext.ts
Comment thread repos/effect/packages/effect/src/Struct.ts Outdated
Comment thread packages/effect-app/src/Schema/ext.ts
Comment thread packages/effect-app/src/Schema/ext.ts Outdated
@patroza

patroza commented Jul 23, 2026

Copy link
Copy Markdown
Member

@MindfulLearner update/resolve reviews when you apply changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants