effect
effect copied to clipboard
Add `optionFromEmptyString`
🚀 Feature request
Current Behavior
At the moment I did define the following schema to handle empty strings as Option.
const optionFromEmptyString = pipe(
Schema.string,
Schema.transform(
Schema.optionFromSelf(Schema.string),
(s) => s.length > 0 ? Option.some(s) : Option.none(),
(s) => Option.getOrElse(s, () => '')
)
)
Desired Behavior
Having the schema implemented in @effect/schema
Suggested Solution
const optionFromEmptyString = pipe(
Schema.string,
Schema.transform(
Schema.optionFromSelf(Schema.string),
(s) => s.length > 0 ? Option.some(s) : Option.none(),
(s) => Option.getOrElse(s, () => '')
)
)
Who does this impact? Who is this for?
I think everyone who uses Schema with front-end forms or where null cannot be used. Eg: forms returns empty strings when are submitted.
Describe alternatives you've considered
Declare the schema at app level.
Additional context
Your environment
| Software | Version(s) |
|---|---|
| @effect/schema | 0.15.1 |
| TypeScript | 5.1.6 |
@FedericoBiccheddu string is already a disjoint union with respect to non empty strings: string = "" + NonEmptyString, what's the benefit of transforming into Option<NonEmptyString>?
Working with data coming from a form and parsing it at the edge, simplify handling the parsed data a lot when working with Option at domain level when values are missing. For example, an empty or missing value coming from the front-end it will be always an empty string (eg: input, select, etc).
https://codesandbox.io/p/sandbox/festive-brook-9v3vgj?file=%2Fsrc%2Froutes%2F%2Bpage.server.ts%3A35%2C1
I created this sandbox to showcase what I think is a very common use-case and try to answer your question.
The sandbox shows how optionFromEmptyString works, however I still don't get:
- in the transformation why the
Toschema isSchema.optionFromSelf(Schema.string)instead ofSchema.optionFromSelf(Schema.string.pipe(Schema.nonEmpty()))? Is it intended? - assuming
To = Schema.optionFromSelf(Schema.string.pipe(Schema.nonEmpty())), how transforming astringinto an equivalent type (Option<NonEmptyString>) makes easier to handle the parsed data?
- Didn't know I can do that. Thank you for pointing it out; I did update my sandbox
- Without transforming in an
Option, every time I want to check if the value is present or not, I should check if it equals to an empty string instead of using a semantic type likeOption.
For example, if we have form when we can choose via a select if we want to use a template before creating something and invite a team member via email, when the template field is empty and/or the field teamInvite is empty, then the form submit "" as value, so in the back we can do something like:
// snip
Effect.gen(function* ($) {
const formData = yield* $(Effect.tryPromise(() => request.formData()))
const payload = yield* $(Schema.parse(payloadS)(Object.fromEntries(formData.entries())))
if (Option.isSome(payload.template)) {
// Apply the logic to use a template
}
if (Option.isSome(payload.teamInvite)) {
// Apply the logic to invite the team, check if there are already members with the email and so on
}
return yield* $(Schema.encode(payloadS)(payload))
}),
// snip
Making this specific example, It made me think that this combinator could receive another schema and the general use case I think still applies.
Closing in favour of https://github.com/Effect-TS/effect/issues/3335
@FedericoBiccheddu you may want to join the discussion here https://discordapp.com/channels/795981131316985866/1265704338257481778/1265949127334826048