Skip to content

Refine existing type in Predicate.isTagged#6497

Open
thewilkybarkid wants to merge 2 commits into
Effect-TS:mainfrom
thewilkybarkid:istagged-refine-v4
Open

Refine existing type in Predicate.isTagged#6497
thewilkybarkid wants to merge 2 commits into
Effect-TS:mainfrom
thewilkybarkid:istagged-refine-v4

Conversation

@thewilkybarkid

@thewilkybarkid thewilkybarkid commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Type

  • Refactor
  • Feature
  • Bug Fix
  • Optimization
  • Documentation Update

Description

This change allows Predicate.isTagged to narrow the type of known tagged structures, rather than turning everything into { _tag: K }. This change does mean that any now remains any, but I can't think of a way around that.

Related

Summary by CodeRabbit

  • Type Improvements
    • Refined Predicate.isTagged type narrowing to preserve more of the original input shape for tagged unions.
    • Improved inference behavior across tagged, unknown, and mixed (tagged + non-tagged) unions, with tighter results for incompatible inputs.
  • Tests
    • Expanded type-level coverage for isTagged to validate narrowing outcomes across multiple input scenarios.

@github-project-automation github-project-automation Bot moved this to Discussion Ongoing in PR Backlog Jul 20, 2026
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7825337

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

This PR includes changesets to release 27 packages
Name Type
effect Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-node-shared Patch
@effect/platform-node Patch
@effect/vitest Patch
@effect/ai-anthropic Patch
@effect/ai-openai-compat Patch
@effect/ai-openai Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/openapi-generator Patch

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

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fff5c8cb-5447-42ce-a982-5cab607306a6

📥 Commits

Reviewing files that changed from the base of the PR and between 7e88ec5 and 7825337.

📒 Files selected for processing (1)
  • .changeset/funny-drinks-scream.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/funny-drinks-scream.md

📝 Walkthrough

Walkthrough

Predicate.isTagged now preserves matching tagged-union members in its type refinements. Type-level tests cover tagged, mixed, unknown, and non-matching inputs, and changeset metadata declares a patch release.

Changes

isTagged refinement

Layer / File(s) Summary
Update isTagged refinement contract
packages/effect/src/Predicate.ts
Predicate.isTagged overloads use Extract<T, { _tag: K }> for object inputs and intersect non-object inputs with the requested tag shape.
Validate tagged-union narrowing
packages/effect/typetest/Predicate.tst.ts, .changeset/funny-drinks-scream.md
Type fixtures and assertions cover tagged unions, mixed unions, unknown values, and non-matching values; changeset metadata declares a patch release.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested labels: bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change to Predicate.isTagged's type refinement.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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

@coderabbitai coderabbitai Bot added the bug Something isn't working label Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/effect/typetest/Predicate.tst.ts (1)

61-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the uncurried overload too.

These assertions only exercise Predicate.isTagged("a"). The changed two-argument overload on Line 1168, used by packages/effect/src/Filter.ts, can regress independently. Add a direct type-level assertion using Predicate.isTagged(value, "a") for both matching and non-matching inputs.

🤖 Prompt for 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.

In `@packages/effect/typetest/Predicate.tst.ts` around lines 61 - 65, Extend the
type-level tests around the existing Predicate.isTagged assertions to cover the
uncurried two-argument overload, using Predicate.isTagged(value, "a") with both
matching and non-matching inputs. Assert the resulting narrowed types for the
matching case and the never/non-match behavior, reusing the existing test values
where appropriate.
🤖 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 @.changeset/funny-drinks-scream.md:
- Line 5: Update the changeset text to reference the exported API as
Predicate.isTagged, replacing the incorrect Predicated.isTagged name while
preserving the rest of the release note.

In `@packages/effect/src/Predicate.ts`:
- Around line 1167-1168: Update both overloads of the tag predicate to replace
the T extends {} conditional with T extends { _tag: K } ? T : T & { _tag: K }.
Preserve precise narrowing for already-tagged unions while allowing broad object
inputs to narrow to the required _tag shape.

---

Nitpick comments:
In `@packages/effect/typetest/Predicate.tst.ts`:
- Around line 61-65: Extend the type-level tests around the existing
Predicate.isTagged assertions to cover the uncurried two-argument overload,
using Predicate.isTagged(value, "a") with both matching and non-matching inputs.
Assert the resulting narrowed types for the matching case and the
never/non-match behavior, reusing the existing test values where appropriate.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 77cc775c-09e1-4a77-b49c-52aa0cd1dc74

📥 Commits

Reviewing files that changed from the base of the PR and between 688d46a and 7e88ec5.

📒 Files selected for processing (3)
  • .changeset/funny-drinks-scream.md
  • packages/effect/src/Predicate.ts
  • packages/effect/typetest/Predicate.tst.ts

Comment thread .changeset/funny-drinks-scream.md Outdated
Comment on lines +1167 to +1168
<K extends string>(tag: K): <T>(self: T) => self is T extends {} ? Extract<T, { _tag: K }> : T & { _tag: K }
<K extends string, T>(self: T, tag: K): self is T extends {} ? Extract<T, { _tag: K }> : T & { _tag: K }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

pnpm test-types packages/effect/typetest/Predicate.tst.ts
rg -n 'ReadonlyArray<object>|Record<string, unknown>|isTagged' packages/effect/typetest packages/effect/src/Predicate.ts

Repository: Effect-TS/effect

Length of output: 535


Preserve narrowing for broad object inputs.

T extends {} routes object and Record<string, unknown> through Extract, which collapses to never for values that can still pass the runtime _tag check. Use T extends { _tag: K } ? T : T & { _tag: K } in both overloads so tagged unions stay precise and broad inputs still narrow correctly.

Suggested refinement
-  <K extends string>(tag: K): <T>(self: T) => self is T extends {} ? Extract<T, { _tag: K }> : T & { _tag: K }
-  <K extends string, T>(self: T, tag: K): self is T extends {} ? Extract<T, { _tag: K }> : T & { _tag: K }
+  <K extends string>(tag: K): <T>(self: T) => self is T extends { _tag: K } ? T : T & { _tag: K }
+  <K extends string, T>(self: T, tag: K): self is T extends { _tag: K } ? T : T & { _tag: K }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<K extends string>(tag: K): <T>(self: T) => self is T extends {} ? Extract<T, { _tag: K }> : T & { _tag: K }
<K extends string, T>(self: T, tag: K): self is T extends {} ? Extract<T, { _tag: K }> : T & { _tag: K }
<K extends string>(tag: K): <T>(self: T) => self is T extends { _tag: K } ? T : T & { _tag: K }
<K extends string, T>(self: T, tag: K): self is T extends { _tag: K } ? T : T & { _tag: K }
🤖 Prompt for 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.

In `@packages/effect/src/Predicate.ts` around lines 1167 - 1168, Update both
overloads of the tag predicate to replace the T extends {} conditional with T
extends { _tag: K } ? T : T & { _tag: K }. Preserve precise narrowing for
already-tagged unions while allowing broad object inputs to narrow to the
required _tag shape.

Source: MCP tools

@github-project-automation github-project-automation Bot moved this from Discussion Ongoing to Waiting on Author in PR Backlog Jul 20, 2026
@thewilkybarkid thewilkybarkid changed the title Refine existing type in Predicated.isTagged Refine existing type in Predicate.isTagged Jul 20, 2026
@IMax153 IMax153 added the 4.0 label Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.0 bug Something isn't working

Projects

Status: Waiting on Author

Development

Successfully merging this pull request may close these issues.

2 participants