Skip to content

[Repo Assist] Fix FSharpOption not recognized as union type in F# reflection#4529

Draft
github-actions[bot] wants to merge 1 commit intomainfrom
repo-assist/fix-issue-4082-option-union-reflection-7d1e11c14993f393
Draft

[Repo Assist] Fix FSharpOption not recognized as union type in F# reflection#4529
github-actions[bot] wants to merge 1 commit intomainfrom
repo-assist/fix-issue-4082-option-union-reflection-7d1e11c14993f393

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Closes #4082

Root Cause

The option_type() function in fable-library-ts/Reflection.ts and fable-library-py/fable_library/reflection.py created a TypeInfo without a cases property. As a result:

  • FSharpType.IsUnion(typeof<option<int>>) returned false
  • FSharpType.GetUnionCases(typeof<option<int>>) threw an exception
  • FSharpValue.GetUnionFields and MakeUnion also failed for option types

Fix

  • Rewrote option_type() to include a cases lazy property exposing None (tag 0) and Some (tag 1) union cases.
  • Added option-aware handling in getUnionFields/get_union_fields: Fable erases the option tag at runtime (None = undefined/null, Some(x) = x or wrapper), so we detect the case from the value itself.
  • Added option-aware handling in makeUnion/make_union to correctly construct None and Some(x) values.

Tests Added

  • tests/Js/Main/ReflectionTests.fs: FSharp.Reflection: Option is a union type
  • tests/Python/TestReflection.fs: test FSharp.Reflection: Option is a union type

Both tests verify IsUnion, GetUnionCases, GetUnionFields, and MakeUnion for option<int>.

Trade-offs

  • No changes to src/Fable.AST/ or src/Fable.Core/ (no breaking changes).
  • Python and TypeScript fixes are aligned, keeping both targets consistent.

Generated by Repo Assist · ● 10.1M ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

FSharpType.IsUnion/GetUnionCases now correctly treats option<'T> as a
union type with two cases (None=tag 0, Some=tag 1), matching .NET
behaviour. FSharpValue.GetUnionFields and MakeUnion are updated to
handle the erased runtime representation of options (None = undefined
in JS/TS, None = None in Python; Some wraps via the Some helper).

Changes:
- src/fable-library-ts/Reflection.ts: add cases to option_type, handle
  option in getUnionFields and makeUnion
- src/fable-library-py/fable_library/reflection.py: same fixes for
  Python using SomeWrapper awareness
- tests/Js/Main/ReflectionTests.fs: add regression test
- tests/Python/TestReflection.fs: add regression test

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation Automated changes bug javascript python Python repo-assist Created by Repo Assist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error: FSharp.Reflection: Microsoft.FSharp.Core.FSharpOption`1 is not an F# union type

0 participants