Skip to content

Commit 32691fd

Browse files
dbrattliclaude
andauthored
fix(stdlib): align Json.getCases return type with Python output (#279)
The F# return type `string array` for `getCases` was inaccurate — Fable union types' `cases()` static method returns `list[str]`, not an FSharpArray. Pyright flagged the resulting `cases: Array[str] = ...` assignment as a type error in the generated Python (issue #278). Change the return type to `ResizeArray<string>` (which maps to Python `list`) and update the call site to use `.Count` instead of `.Length`. Both compile to `len(...)` so runtime behavior is unchanged. Also wire up pyright in CI to catch future regressions: add a `just pyright` recipe scoped to `build/stdlib`, run it in the build-and-test workflow, and bump pyright to 1.1.409. Fable codegen-artifact rules (`reportUnusedImport`, `reportInvalidTypeVarUse`) are disabled since those are emitted by the compiler, not the bindings. Closes #278 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0639c9a commit 32691fd

5 files changed

Lines changed: 45 additions & 5 deletions

File tree

.github/workflows/build-and-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,8 @@ jobs:
4545
- name: Build
4646
run: just build
4747

48+
- name: Pyright type check
49+
run: just pyright
50+
4851
- name: Test
4952
run: just test

justfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ test-python: build
5757
{{fable}} {{test_path}} --lang Python --outDir {{build_path}}/tests
5858
uv run pytest {{build_path}}/tests
5959

60+
# Type-check the generated Python bindings with pyright (see issue #278)
61+
pyright: build
62+
uv run pyright
63+
6064
# Create NuGet package with version from CHANGELOG.md
6165
pack:
6266
#!/usr/bin/env bash

pyproject.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ readme = "README.md"
88
license = "MIT"
99
dependencies = [
1010
"fable-library==5.0.0",
11+
"pyright>=1.1.409",
1112
]
1213

1314
[project.urls]
@@ -67,10 +68,16 @@ indent-style = "space"
6768
line-ending = "auto"
6869

6970
[tool.pyright]
71+
# Type-check the Fable-generated Python bindings in build/stdlib so the shipped
72+
# output stays clean for downstream pyright users (see issue #278).
73+
include = ["build/stdlib"]
7074
reportMissingTypeStubs = false
7175
reportMissingImports = false
7276
reportUnnecessaryTypeIgnoreComment = true
73-
reportUnusedImport = true
77+
# Disabled: Fable emits unused `UNIT` imports and single-occurrence TypeVars
78+
# from F# generics. Those are codegen artifacts, not bindings bugs.
79+
reportUnusedImport = false
80+
reportInvalidTypeVarUse = false
7481
reportUnusedVariable = true
7582
reportUnnecessaryIsInstance = true
7683
reportUnnecessaryComparison = true
@@ -83,4 +90,4 @@ reportOverlappingOverload = true
8390
reportInconsistentConstructor = true
8491
reportImplicitStringConcatenation = true
8592
pythonVersion = "3.12"
86-
typeCheckingMode = "basic"
93+
typeCheckingMode = "standard"

src/stdlib/Json.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ let private slotsToDict (o: obj) : obj = nativeOnly
8888
let private unionToList (o: obj) (caseName: string) : obj = nativeOnly
8989

9090
[<Emit("getattr(type($0), 'cases', lambda: [])()")>]
91-
let private getCases (o: obj) : string array = nativeOnly
91+
let private getCases (o: obj) : ResizeArray<string> = nativeOnly
9292

9393
[<Emit("(_ for _ in ()).throw(TypeError(f'Object of type {type($0).__name__} is not JSON serializable'))")>]
9494
let private raiseTypeError (o: obj) : obj = nativeOnly
@@ -136,7 +136,7 @@ let fableDefault (o: obj) : obj =
136136
let tag: int = getattr o "tag" :?> int
137137

138138
let caseName =
139-
if tag < cases.Length then
139+
if tag < cases.Count then
140140
cases.[tag]
141141
else
142142
"Case" + string tag

uv.lock

Lines changed: 27 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)