Skip to content

Commit

Permalink
remove type-level error message from optional signature, closes #3290
Browse files Browse the repository at this point in the history
… (#3291)
  • Loading branch information
gcanti authored Jul 17, 2024
1 parent f0285d3 commit 8ec4955
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
7 changes: 7 additions & 0 deletions .changeset/moody-maps-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@effect/schema": patch
---

remove type-level error message from `optional` signature, closes #3290

This fix eliminates the type-level error message from the `optional` function signature, which was causing issues in generic contexts.
16 changes: 13 additions & 3 deletions packages/schema/dtslint/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,6 @@ S.Struct({ a: S.String.pipe(S.optional({ exact: true })) })
// optional - Errors
// ---------------------------------------------

// @ts-expect-error
S.Boolean.pipe(S.optional)

// @ts-expect-error
S.optional(S.String, { as: "Option", default: () => "" })

Expand Down Expand Up @@ -559,6 +556,19 @@ S.optional(S.String, { as: null })
// @ts-expect-error
S.optional(S.String, { default: null })

// ---------------------------------------------
// optional() used in a generic context
// ---------------------------------------------

type TypeWithValue<Value extends S.Schema.Any> = { value: S.optionalWithOptions<Value, { nullable: true }> }

const makeTypeWithValue = <Value extends S.Schema.Any>(value: Value): TypeWithValue<Value> => ({
value: S.optional(value, { nullable: true })
})

// $ExpectType TypeWithValue<typeof String$>
makeTypeWithValue(S.String)

// ---------------------------------------------
// optional()
// ---------------------------------------------
Expand Down
5 changes: 1 addition & 4 deletions packages/schema/src/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2243,13 +2243,10 @@ export const optional: {
options?: Options
): (self: S) => [undefined] extends [Options] ? optional<S> : optionalWithOptions<S, Options>
<S extends Schema.All, Options extends OptionalOptions<Schema.Type<S>>>(
self: Schema.All extends S ? "you can't apply optional implicitly, use optional() instead" : S,
self: S,
options?: Options
): [undefined] extends [Options] ? optional<S> : optionalWithOptions<S, Options>
} = dual((args) => isSchema(args[0]), (from, options) => {
// Note: `Schema.All extends S ? "you can't...` is used to prevent the case where `optional` is implicitly applied.
// For example: `S.String.pipe(S.optional)` would result in `S.String` being inferred as `Schema.All`,
// which is not the intended behavior. This is mostly an aesthetic consideration, so if it causes issues, we can remove it.
return new PropertySignatureWithFromImpl(optionalPropertySignatureAST(from, options), from)
})

Expand Down

0 comments on commit 8ec4955

Please sign in to comment.