Skip to content

feat: improve type narrowing with assertion signature overloads#39

Merged
hughgrigg merged 33 commits into
mainfrom
feat/hg/improve-typing-overloads
Jun 15, 2026
Merged

feat: improve type narrowing with assertion signature overloads#39
hughgrigg merged 33 commits into
mainfrom
feat/hg/improve-typing-overloads

Conversation

@hughgrigg

@hughgrigg hughgrigg commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Significantly improved TypeScript type narrowing for many assertion helpers (arrays, strings, objects, UUIDs, and primitives), including better preservation of literal and union shapes.
    • More consistent, clearer assertion failure messages for invalid input types and edge cases.
  • Bug Fixes
    • Corrected type-narrowing behavior for identical-value assertions.
    • Expanded UUID v4 type matching to include additional variant characters.
  • Tests
    • Expanded Vitest coverage with more type-level (expectTypeOf) and runtime error-message assertions.

hughgrigg added 30 commits June 15, 2026 09:49
@hughgrigg hughgrigg self-assigned this Jun 15, 2026
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ed784b86-3f8e-4fa6-a7af-8775f9c51989

📥 Commits

Reviewing files that changed from the base of the PR and between d855819 and edfb268.

📒 Files selected for processing (1)
  • src/assert/instance-of/instance-of.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/assert/instance-of/instance-of.test.ts

📝 Walkthrough

Walkthrough

Adds TypeScript overload sets and refinement hooks across all assertion functions in the library. Each assertion now accepts either a typed input (TArray extends unknown[], TActual extends string, etc.) or unknown, with correspondingly narrowed asserts value is return types. Matchers gain element-type generics, type files add element-extraction helpers and optional [refinement] callbacks, and centralized message-builder helpers replace inline error strings. Tests are extended with expectTypeOf narrowing assertions throughout.

Changes

Assertion library type-narrowing overhaul

Layer / File(s) Summary
Type-file contracts: helpers, refinement hooks, matcher generics
src/assert/array-includes-all/array-includes-all.type.ts, src/assert/array-includes/array-includes.type.ts, src/assert/array-not-empty/array-not-empty.type.ts, src/assert/instance-of/instance-of.type.ts, src/assert/non-nullable/non-nullable.type.ts, src/assert/uuid/uuid-v4.type.ts, src/assert/object-matches/object-matches.type.ts
Adds ArrayElement, ArrayIncludingAllElement, ArrayIncludingAllRefinement, ClassConstructor, InstanceOfRefinement, UuidV4Variant; updates ArrayIncludingAllMatcher/InstanceOfMatcher/NonNullableMatcher with optional [refinement] hooks; changes NonEmptyArray from readonly to mutable; fixes two-parameter inference in RefineMatcherResult.
Array assertion overloads and matcher updates
src/assert/array-includes-all/array-includes-all.assert.ts, src/assert/array-includes-all/array-includes-all.match.ts, src/assert/array-includes-all/array-includes-all.test.ts, src/assert/array-includes/array-includes.assert.ts, src/assert/array-includes/array-includes.match.ts, src/assert/array-includes/array-includes.test.ts, src/assert/array-length/array-length.assert.ts, src/assert/array-length/array-length.test.ts, src/assert/array-min-length/array-min-length.assert.ts, src/assert/array-min-length/array-min-length.test.ts, src/assert/array-not-empty/array-not-empty.assert.ts, src/assert/array-not-empty/array-not-empty.test.ts
Converts all array assert functions to TArray/unknown overload pairs; removes assertNonNullable pre-checks; adds buildArrayXxxMessage helpers distinguishing non-array vs wrong-length errors; updates matchers to propagate element types; extends tests with new error-message and expectTypeOf narrowing assertions.
String assertion overloads with conditional helper types
src/assert/string-includes/string-includes.assert.ts, src/assert/string-not-includes/string-not-includes.assert.ts, src/assert/string-starts-with/string-starts-with.assert.ts, src/assert/string-ends-with/string-ends-with.assert.ts, src/assert/string-length/string-length.assert.ts, src/assert/string-*/string-*.test.ts
Adds internal conditional types (StringIncluding, StringNotIncluding, StringStartingWith) and two-overload patterns for each string assertion; converts implementations to value: unknown + void; adds buildStringXxxMessage helpers; tests cover non-string error paths and expectTypeOf narrowing for unknown, union, and overlap cases.
Other assertion overloads: instance-of, non-nullable, object, UUID, primitives
src/assert/instance-of/instance-of.assert.ts, src/assert/instance-of/instance-of.match.ts, src/assert/non-nullable/non-nullable.match.ts, src/assert/identical/identical.assert.ts, src/assert/object-has-property/object-has-property.assert.ts, src/assert/uuid/uuid-v4.assert.ts, src/assert/type-*/..., src/assert/*/...test.ts
Applies the overload+refinement pattern to assertInstanceOf (new InstanceOfAssertion conditional), nonNullable (removes generic, uses NonNullable<unknown>), assertIdentical (asserts TExpected not typeof expected), assertObjectHasProperty (unknown overload), assertUuidV4 (TActual & UuidV4 overload); all primitive type assertions and remaining assert functions receive expectTypeOf narrowing tests.
Tooling: ESLint type-file override and build-script deduplication
eslint.config.ts, scripts/build-readme-lists.sh
Disables @typescript-eslint/no-unused-vars for **/*.type.ts files; deduplicates exported function names via sort -u before counting in the README build script.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Hoppity-hop through the type maze I go,
Overloads blooming like clover in a row!
TArray, unknown, both get their say,
Narrowing types in the most precise way.
No more assertNonNullable in array land,
Each buildXxxMessage helper close at hand.
The rabbit types true — and the tests all pass! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main objective: improving type narrowing across multiple assertion functions by introducing signature overloads for better TypeScript type inference.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/hg/improve-typing-overloads

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/assert/instance-of/instance-of.test.ts`:
- Line 89: Fix the typo in the test name for the test case that checks
structural intersection behavior. In the it() function call with the test
description, change "preservers" to "preserves" to correct the grammatical error
in the test name.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 045e24f5-2c37-4a94-ad8a-fcf0cd5efebe

📥 Commits

Reviewing files that changed from the base of the PR and between 773847c and d855819.

📒 Files selected for processing (57)
  • eslint.config.ts
  • scripts/build-readme-lists.sh
  • src/assert/array-includes-all/array-includes-all.assert.ts
  • src/assert/array-includes-all/array-includes-all.match.ts
  • src/assert/array-includes-all/array-includes-all.test.ts
  • src/assert/array-includes-all/array-includes-all.type.ts
  • src/assert/array-includes/array-includes.assert.ts
  • src/assert/array-includes/array-includes.match.ts
  • src/assert/array-includes/array-includes.test.ts
  • src/assert/array-includes/array-includes.type.ts
  • src/assert/array-length/array-length.assert.ts
  • src/assert/array-length/array-length.test.ts
  • src/assert/array-min-length/array-min-length.assert.ts
  • src/assert/array-min-length/array-min-length.test.ts
  • src/assert/array-not-empty/array-not-empty.assert.ts
  • src/assert/array-not-empty/array-not-empty.test.ts
  • src/assert/array-not-empty/array-not-empty.type.ts
  • src/assert/buffer-equal/buffer-equal.test.ts
  • src/assert/identical/identical.assert.ts
  • src/assert/identical/identical.test.ts
  • src/assert/instance-of/instance-of.assert.ts
  • src/assert/instance-of/instance-of.match.ts
  • src/assert/instance-of/instance-of.test.ts
  • src/assert/instance-of/instance-of.type.ts
  • src/assert/non-nullable/non-nullable.match.ts
  • src/assert/non-nullable/non-nullable.test.ts
  • src/assert/non-nullable/non-nullable.type.ts
  • src/assert/number-to-nearest/number-to-nearest.test.ts
  • src/assert/object-equals/object-equals.test.ts
  • src/assert/object-has-property/object-has-property.assert.ts
  • src/assert/object-has-property/object-has-property.test.ts
  • src/assert/object-matches/object-matches.type.ts
  • src/assert/one-of/one-of.test.ts
  • src/assert/string-ends-with/string-ends-with.assert.ts
  • src/assert/string-ends-with/string-ends-with.test.ts
  • src/assert/string-includes/string-includes.assert.ts
  • src/assert/string-includes/string-includes.test.ts
  • src/assert/string-length/string-length.assert.ts
  • src/assert/string-length/string-length.test.ts
  • src/assert/string-not-includes/string-not-includes.assert.ts
  • src/assert/string-not-includes/string-not-includes.test.ts
  • src/assert/string-starts-with/string-starts-with.assert.ts
  • src/assert/string-starts-with/string-starts-with.test.ts
  • src/assert/true/true.test.ts
  • src/assert/type-bigint/type-bigint.test.ts
  • src/assert/type-boolean/type-boolean.test.ts
  • src/assert/type-function/type-function.test.ts
  • src/assert/type-number/type-number.test.ts
  • src/assert/type-numeric/type-numeric.test.ts
  • src/assert/type-object/type-object.test.ts
  • src/assert/type-string/type-string.test.ts
  • src/assert/type-symbol/type-symbol.test.ts
  • src/assert/type-typed-array/type-typed-array.test.ts
  • src/assert/undefined/undefined.test.ts
  • src/assert/uuid/uuid-v4.assert.ts
  • src/assert/uuid/uuid-v4.test.ts
  • src/assert/uuid/uuid-v4.type.ts

Comment thread src/assert/instance-of/instance-of.test.ts Outdated
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@hughgrigg hughgrigg merged commit e51c12a into main Jun 15, 2026
4 checks passed
@hughgrigg hughgrigg deleted the feat/hg/improve-typing-overloads branch June 15, 2026 13:07
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.

1 participant