Skip to content

Commit

Permalink
Fix constructor type inference for classes with all optional fields, … (
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored May 31, 2024
1 parent 6801fca commit 5745886
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 4 deletions.
7 changes: 7 additions & 0 deletions .changeset/quiet-lions-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@effect/schema": patch
---

Fix constructor type inference for classes with all optional fields, closes #

This fix addresses an issue where TypeScript incorrectly inferred the constructor parameter type as an empty object {} when all class fields were optional. Now, the constructor properly recognizes arguments as objects with optional fields (e.g., { abc?: number, xyz?: number }).
10 changes: 9 additions & 1 deletion packages/schema/dtslint/Class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class NoFields extends S.Class<NoFields>("NoFields")({}) {}
// $ExpectType [props?: void | {}, disableValidation?: boolean | undefined]
hole<ConstructorParameters<typeof NoFields>>()

new NoFields()

new NoFields({})

// ---------------------------------------------
// A class with all fields with a default should permit an empty argument in the constructor.
// ---------------------------------------------
Expand All @@ -18,9 +22,13 @@ class AllDefaultedFields extends S.Class<AllDefaultedFields>("AllDefaultedFields
a: S.String.pipe(S.propertySignature, S.withConstructorDefault(() => ""))
}) {}

// $ExpectType [props?: void | {}, disableValidation?: boolean | undefined]
// $ExpectType [props?: void | { readonly a?: string; }, disableValidation?: boolean | undefined]
hole<ConstructorParameters<typeof AllDefaultedFields>>()

new AllDefaultedFields()

new AllDefaultedFields({})

// ---------------------------------------------
// test Context
// ---------------------------------------------
Expand Down
11 changes: 9 additions & 2 deletions packages/schema/dtslint/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,13 @@ const make2 = S.Struct({
// $ExpectType { readonly a?: string; readonly b: number; readonly c?: boolean; }
hole<Parameters<typeof make2>["0"]>()

const make3 = S.Struct({
a: S.withConstructorDefault(S.propertySignature(S.String), () => "")
}).make

// $ExpectType { readonly a?: string; }
hole<Parameters<typeof make3>["0"]>()

class AA extends S.Class<AA>("AA")({
a: S.propertySignature(S.String).pipe(S.withConstructorDefault(() => "")),
b: S.Number,
Expand Down Expand Up @@ -2390,11 +2397,11 @@ S.asSchema(S.Struct({ a: S.optional(S.String).pipe(S.withDefaults({ decoding: ()
// $ExpectType Struct<{ a: PropertySignature<":", string, never, "?:", string | undefined, true, never>; }>
S.Struct({ a: S.optional(S.String).pipe(S.withDefaults({ decoding: () => "", constructor: () => "" })) })

const make3 =
const make4 =
S.Struct({ a: S.optional(S.String).pipe(S.withDefaults({ decoding: () => "", constructor: () => "" })) }).make

// $ExpectType { readonly a?: string; }
hole<Parameters<typeof make3>["0"]>()
hole<Parameters<typeof make4>["0"]>()

// ---------------------------------------------
// Schema.AsSchema
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/src/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6684,7 +6684,7 @@ export interface Class<Self, Fields extends Struct.Fields, I, R, C, Inherited, P
extends Schema<Self, Types.Simplify<I>, R>
{
new(
props: RequiredKeys<C> extends never ? void | {} : Types.Simplify<C>,
props: RequiredKeys<C> extends never ? void | Types.Simplify<C> : Types.Simplify<C>,
disableValidation?: boolean | undefined
): Struct.Type<Fields> & Omit<Inherited, keyof Fields> & Proto
Expand Down

0 comments on commit 5745886

Please sign in to comment.