Summary
When src/stdlib/Json.fs is transpiled to Python and consumed by a project that runs pyright in standard mode, a type error is reported in the generated json.py:
json.py:29:37 - error: Type "Any | list[Unknown]" is not assignable to declared type "Array"
"list[Unknown]" is not assignable to "FSharpArray[str]" (reportAssignmentType)
The offending generated line:
cases: Array[str] = getattr(type(o), 'cases', lambda: [])()
This surfaced when bumping Fable.Python from 4.24.0 to 5.0.0 in the Fable repo's Python test project (fable-compiler/Fable#4571 — pyright CI job).
Root cause
In src/stdlib/Json.fs (around line 90):
[<Emit("getattr(type($0), 'cases', lambda: [])()")>]
let private getCases (o: obj) : string array = nativeOnly
The F# return type string array becomes Array[str] (FSharpArray) in the generated Python annotation. But the emit's default branch (lambda: []) returns a plain Python list, not an FSharpArray — so pyright infers the expression's type as Any | list[Unknown], which doesn't satisfy Array[str].
The Fable.Python.Json module is new in v5.0.0 (introduced by #175, expanded in #182 and #184), so this error didn't exist on 4.24.0.
Reproduction
- In a project referencing
Fable.Python 5.0.0, transpile any F# file that pulls in Fable.Python.Json.
- Run
pyright (standard mode, default settings) over the resulting fable_modules/fable_python/stdlib/json.py.
- Observe the error above on line 29.
Suggested directions
getCases is only used inside fableDefault to read cases.Length and cases.[tag], so the implementation has flexibility. Some options:
- Replace the
Emit with plain F# using the existing private hasattr / getattr helpers to check for cases on type(o) and call it — returning [||] when absent. This keeps the F# type honest and lets Fable generate well-typed Python.
- Change the return type to something the emit actually produces (e.g. a
seq) and adapt call sites.
- Inline the lookup at the call site so no separate helper is needed.
# type: ignore / cast(Any, ...) / excluding the file are not great options — they hide a real type mismatch.
Workaround for downstream users
Add **/fable_modules/fable_python/stdlib/json.py to the exclude list in the consuming project's pyrightconfig.json until a fix is released.
Summary
When
src/stdlib/Json.fsis transpiled to Python and consumed by a project that runs pyright in standard mode, a type error is reported in the generatedjson.py:The offending generated line:
This surfaced when bumping
Fable.Pythonfrom4.24.0to5.0.0in the Fable repo's Python test project (fable-compiler/Fable#4571 — pyright CI job).Root cause
In
src/stdlib/Json.fs(around line 90):The F# return type
string arraybecomesArray[str](FSharpArray) in the generated Python annotation. But the emit's default branch (lambda: []) returns a plain Pythonlist, not an FSharpArray — so pyright infers the expression's type asAny | list[Unknown], which doesn't satisfyArray[str].The
Fable.Python.Jsonmodule is new inv5.0.0(introduced by #175, expanded in #182 and #184), so this error didn't exist on4.24.0.Reproduction
Fable.Python5.0.0, transpile any F# file that pulls inFable.Python.Json.pyright(standard mode, default settings) over the resultingfable_modules/fable_python/stdlib/json.py.Suggested directions
getCasesis only used insidefableDefaultto readcases.Lengthandcases.[tag], so the implementation has flexibility. Some options:Emitwith plain F# using the existing privatehasattr/getattrhelpers to check forcasesontype(o)and call it — returning[||]when absent. This keeps the F# type honest and lets Fable generate well-typed Python.seq) and adapt call sites.# type: ignore/cast(Any, ...)/ excluding the file are not great options — they hide a real type mismatch.Workaround for downstream users
Add
**/fable_modules/fable_python/stdlib/json.pyto theexcludelist in the consuming project'spyrightconfig.jsonuntil a fix is released.