Skip to content

Fix rx.cond literal string typing#6545

Open
Alek99 wants to merge 2 commits into
mainfrom
fix-cond-literal-typing
Open

Fix rx.cond literal string typing#6545
Alek99 wants to merge 2 commits into
mainfrom
fix-cond-literal-typing

Conversation

@Alek99
Copy link
Copy Markdown
Member

@Alek99 Alek99 commented May 20, 2026

Summary

Preserve literal string unions in rx.cond overloads so expressions like rx.cond(State.condition, "green", "red") type as Var[Literal["green", "red"]] instead of widening to Var[str].

This fixes Pyright errors when passing conditional literal values to props typed as Literal[...] | Var[Literal[...]], such as Radix color_scheme.

Fixes #6538

Validation

  • uv run ruff format packages/reflex-components-core/src/reflex_components_core/core/cond.py tests/units/components/core/test_cond.py
  • uv run ruff check packages/reflex-components-core/src/reflex_components_core/core/cond.py tests/units/components/core/test_cond.py
  • PYRIGHT_PYTHON_FORCE_VERSION=latest uv run pyright tests/units/components/core/test_cond.py packages/reflex-components-core/src/reflex_components_core/core/cond.py --pythonversion 3.14
  • uv run pytest tests/units/components/core/test_cond.py

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 20, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing fix-cond-literal-typing (6a66f73) with main (bf2deed)

Open in CodSpeed

@Alek99 Alek99 marked this pull request as ready for review May 20, 2026 20:03
@Alek99 Alek99 requested a review from a team as a code owner May 20, 2026 20:03
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 20, 2026

Greptile Summary

This PR adds three new @overload signatures to rx.cond using a LiteralString-bounded TypeVar S, so that expressions like rx.cond(state.flag, \"green\", \"red\") now type-check as Var[Literal[\"green\", \"red\"]] instead of widening to Var[str].

  • Adds S = TypeVar(\"S\", bound=LiteralString) and three overloads covering (S, S), (S, Var[U]), and (Var[T], S) argument combinations, placed before the more general T/U overloads so Pyright resolves them first.
  • Updates test_cond_assert_types to expect narrower Var[Literal[...]] return types; however, several new assertions use var_str: Var[str] (an explicitly annotated variable) while expecting Var[Literal[\"a\", ...]] — Pyright typically uses the declared type for overload resolution, so those assert_type calls may not match Pyright's actual inference.

Confidence Score: 3/5

Runtime behavior is unchanged and the new overloads are logically sound, but several test assertions rely on Pyright narrowing an explicitly-typed Var[str] variable to Var[Literal["a"]], which is inconsistent with how Pyright handles declared-type annotations.

The core overload additions look correct and the feature goal is well-motivated. The concern is in the test file: var_str is declared Var[str] but multiple assert_type calls expect Var[Literal["a", ...]]. If Pyright does not narrow through the explicit annotation, those assertions are wrong, meaning the Pyright validation step described in the PR does not actually validate what the comments claim.

tests/units/components/core/test_cond.py — assertions involving var_str at lines 191, 200, 212, and 215 should be re-examined; consider re-declaring var_str as Var[Literal["a"]] or replacing those cases with direct LiteralVar.create calls.

Important Files Changed

Filename Overview
packages/reflex-components-core/src/reflex_components_core/core/cond.py Adds three new overloads using a LiteralString-bounded TypeVar S to preserve literal string types through rx.cond; logic looks correct and ordering is appropriate.
tests/units/components/core/test_cond.py New assert_type checks use var_str declared as Var[str] but expect Var[Literal["a", ...]] behavior, which is inconsistent with Pyright's treatment of explicitly-annotated variables.

Comments Outside Diff (1)

  1. tests/units/components/core/test_cond.py, line 168-170 (link)

    P1 Test variable declared as Var[str] but used as if Var[Literal["a"]]

    var_str is explicitly annotated as Var[str], yet several assert_type calls (lines 191, 200, 212, 215) expect Pyright to treat it as Var[Literal["a"]]. Because Pyright uses the declared type for overload resolution on explicitly-annotated variables, cond(True, "hello", var_str) would resolve U = str in the S, Var[U] overload and produce Var[str], not Var[Literal["hello", "a"]]. The assert_type on line 191 should therefore fail the Pyright check claimed in the PR description. Declaring var_str as var_str: Var[Literal["a"]] (or using LiteralVar.create directly in the assertion, as the new lines 194-196 and 203-206 already do) would make the tests self-consistent and correct.

Reviews (1): Last reviewed commit: "Preserve literal string types in cond" | Re-trigger Greptile

Comment thread packages/reflex-components-core/src/reflex_components_core/core/cond.py Outdated
Comment thread tests/units/components/core/test_cond.py
Comment on lines +191 to +192
# literal str, literal Var[str] -> Var[Literal[...]]
_ = assert_type(cond(True, "hello", literal_var_str), Var[Literal["hello", "a"]])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the comments are confusing, literal str makes sense, but literal Var[str] when it's actually Var[LiteralString] is rather confusing

Comment on lines +185 to +186
# literal str, literal str -> Var[Literal[...]]
_ = assert_type(cond(True, "hello", "world"), Var[Literal["hello", "world"]])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it would be nice to have another test for T, T, now that strings are handled differently

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.

Type errors when using rx.cond on a "Literal" argument

2 participants