Skip to content

feat(type-plus)!: merge Equal into IsEqual<$O>, migrate IsLiteral and Some (#707) - #709

Merged
unional merged 1 commit into
mainfrom
feat-is-equal-options-707
Sep 23, 2026
Merged

unional merged 1 commit into
mainfrom
feat-is-equal-options-707

Conversation

@unional

@unional unional commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Closes #707. Closes #334. Resolves #275: the filter form it asked for is IsNotEqual<A, B, { selection: 'filter' }>, which keeps A when it differs from B.

What changed

1. Equal merged into IsEqual. IsEqual<A, B, $O> now uses Equal's body and its namespace ($Options, $Default, $Branch, $Fn, $Same, $ToProps, _ExactEqual*). Equal is deleted. Its spec is folded into is_equal.spec.ts, and the function-parameter recursion now calls IsEqual itself. The commented-out alternate implementation was dropped. testType.equal still goes through IsEqual and is unchanged.

  • $Options extends $Selection.Options (the full set, not the $BaseOptions Equal used), so { selection: 'filter' } works. Filter returns A.
  • IsNotEqual<A, B, $O> mirrors it and gains $Branch and $Fn. NotEqual is removed.
  • IdentityEqual is removed. It had more callers than the issue listed: is_object.ts and is_not_object.ts used it too. All callers now use IsEqual.$Same.
  • Internal positional call sites moved onto $O: ArrayPlus.Filter, ArrayPlus.IndexAt, Some.StrictArray.

Behavior change (in the changeset): two distinct unique symbols now compare false, and so does a unique symbol against symbol. Two assertions flip: is_equal.spec.ts (testType.equal<typeof s, symbol>) and tuple.spec.ts:43 (['a'] & symbol vs symbol).

2. IsLiteral<T, $O> is wired like the #677 types: $Options, $Default and $Branch, branches resolved through $ResolveBranch, filter returns T.

2b. Some<A, Criteria, $O>. Decision on the open question: Mode moves into $O as { mode: 'strict' | 'loose' }, next to selection and the branch overrides. This is the consistent answer, and 8.0.0 has no compatibility window to protect. Some<A, C, 'strict'> becomes Some<A, C, { mode: 'strict' }>. Filter returns the whole array A. The internal helpers take a pre-resolved { $then; $else } object (Some._Branches). They recurse on Tail<A>, so the filter subject has to be fixed to the whole A before they run.

3. Removed CanAssign, StrictCanAssign, IsAssign, Extendable, NotExtendable, IsExtend and IsNotExtend. Extends.ts is deleted. CanAssign.ts now holds only the runtime canAssign(), whose types now use Assignable and an inline conditional. The internal call sites (PadStart, Some.LooseArray) use Assignable. Specs that used CanAssign/StrictCanAssign as a tool now use Assignable (with { distributive: false } where needed).

4. IsDisjoint gets a TSDoc note explaining that it deliberately takes no options. StringIncludes gets a note explaining why it stays positional.

Sweep

The multi-line sweep from the issue now returns only StringIncludes and NotUnknownOr, plus the known false positives ($Selection.Invert, $Distributive.Parse, $Exact.Parse, and the _*OrElse helpers).

Docs

Migration guide: the old deprecated-alias table is gone. Every removal now sits in the "what moved in 8.0.0" table, and the symbol paragraph is now a behavior-change note. Also updated: the website API pages (equality, testing, array, type-guards-and-assertions, type-functions), packages/type-plus/readme.md, src/array/readme.md, src/assertion/readme.md, and the regenerated llms.txt.

Error snapshot

Updated. The options_Equal_typo probe is replaced by typo and wrong-value probes for IsEqual, IsNotEqual, IsLiteral and Some. Some's mode union is declared 'loose' | 'strict' because TS 5.4 and TS 7 print 'strict' | 'loose' in different orders.

Verification

  • pnpm verify:pkg: test:type on TS 5.4, 5.5, 5.6, 6.0 and 7, test:errors, build, verify:dts, coverage, size — all pass.
  • pnpm docs:llms:check passes.
  • biome passes on every tracked file.
  • The full pnpm verify failed in my worktree only because biome picked up a local, untracked .agents/ file that CI never sees.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f1fef6d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
type-plus Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov

codecov Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (3dc855f) to head (f1fef6d).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #709   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           43        43           
  Lines          231       231           
  Branches        51        51           
=========================================
  Hits           231       231           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@unional
unional enabled auto-merge September 23, 2026 05:34
… Some

- IsEqual<A, B, $O> takes Equal's body and namespace; Equal is removed.
  Two distinct unique symbols (and a unique symbol vs symbol) now compare
  not equal.
- IsNotEqual<A, B, $O> mirrors it; NotEqual is removed. The filter form
  answers #275.
- IdentityEqual is removed in favor of IsEqual.$Same.
- IsLiteral and Some take $O; Some's Mode folds into { mode }.
- Remove CanAssign, StrictCanAssign, IsAssign, Extendable, NotExtendable,
  IsExtend and IsNotExtend.
- Note the no-options design on IsDisjoint and the positional one on
  StringIncludes.

Closes #707

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@unional
unional force-pushed the feat-is-equal-options-707 branch from 8162096 to f1fef6d Compare September 23, 2026 07:27
@unional
unional added this pull request to the merge queue Sep 23, 2026
Merged via the queue into main with commit a1fa278 Sep 23, 2026
7 checks passed
@unional
unional deleted the feat-is-equal-options-707 branch September 23, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant