Skip to content

fix(validator): resolve inline rule overload#43

Merged
SrHenry merged 3 commits into
developerfrom
fix/create-inline-rule-overload
May 27, 2026
Merged

fix(validator): resolve inline rule overload#43
SrHenry merged 3 commits into
developerfrom
fix/create-inline-rule-overload

Conversation

@SrHenry

@SrHenry SrHenry commented May 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix createInlineRule overload resolution for named rules when only TSubject is explicit
  • Add regression coverage for createInlineRule('name', predicate)
  • Preserve existing runtime behavior

Closes #40

Verification

  • yarn run check
  • yarn test
  • yarn tsc -p tsconfig.json --noEmit
  • yarn build

SrHenry added 2 commits May 26, 2026 23:34
Add tests for 1-arg anonymous form and 1-arg with explicit TSubject
to guard against overload resolution regressions.
@SrHenry

SrHenry commented May 27, 2026

Copy link
Copy Markdown
Owner Author

Review follow-up: added missing test coverage for anonymous overload variants

The overload reordering in this fix is correct, but the original test file only covered the 2-argument named forms. Since the fix is fundamentally about overload resolution with explicit type parameters, I've added two test cases:

  1. 1-arg anonymous formcreateInlineRule((value: string) => value.length > 0) returns Custom.Rule.<anonymous>. Guards against the anonymous overload being shadowed by future overload changes.

  2. 1-arg with explicit TSubjectcreateInlineRule<string>(value => value.length > 0) still resolves to the anonymous overload (not the 2-arg overload). This is the exact pattern used in production at SchemaValidator.spec.ts:147 and is directly relevant to the bug being fixed.

All 4 tests pass, lint is clean.

The args.reverse() pattern was non-obvious and relied on in-place
mutation to destructure positional args in reverse order. Replace with
a simple args.length check that reads left-to-right, matching the
overload signatures. Also remove stale commented-out code.

Add type-level tests using expectTypeOf for all overload variants
and a runtime test for the both-type-params-explicit form.
@SrHenry

SrHenry commented May 27, 2026

Copy link
Copy Markdown
Owner Author

Follow-up: implementation improvements and type-level test coverage

1. Replaced args.reverse() with length-based dispatch

The original implementation used args.reverse() to destructure positional args in reverse order — a non-obvious pattern that relied on in-place array mutation and required type assertions to work. Replaced with a straightforward args.length check that reads left-to-right, matching the overload signatures directly.

Before:

const [predicate, name = InlineRuleName] = args.reverse() as ...

After:

if (args.length === 1) {
  return createRule({ name: InlineRuleName, handler: createRuleHandler(args[0]) })()
}
return createRule({ name: args[0], handler: createRuleHandler(args[1]) })()

This also eliminates the non-null assertion (second!) that was needed with the destructuring approach, fixing a biome lint warning.

2. Removed stale commented-out code

The file had 3 lines of commented-out original implementation at the top that served no purpose.

3. Added expectTypeOf type-level tests

Since this fix is fundamentally a type-level fix (overload resolution), runtime tests alone are insufficient. Added a describe('type inference') block with 5 expectTypeOf assertions covering all overload variants:

Call pattern Expected rule[0] type
createInlineRule('hasLength', ...) 'hasLength' (literal)
createInlineRule<string>('hasLength', ...) string (widened)
createInlineRule(predicate) InlineRuleName
createInlineRule<string>(predicate) InlineRuleName
createInlineRule<string, 'hasLength'>(...) 'hasLength' (literal)

These assert the exact return type at compile time, catching any future overload regressions that runtime tests would miss.

4. Added runtime test for both-type-params-explicit form

createInlineRule<string, 'hasLength'>('hasLength', ...) was not covered by any test. Added.

All 358 tests pass, lint clean, typecheck clean.

@SrHenry SrHenry merged commit dc4c1d1 into developer May 27, 2026
2 checks passed
@SrHenry SrHenry deleted the fix/create-inline-rule-overload branch May 27, 2026 05:15
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.

fix: createInlineRule named overload unreachable when only TSubject is provided as explicit type param

1 participant