What
Dagster wires asset dependencies together by matching a parameter name to an upstream AssetKey string, not by an actual Python reference/call:
@asset
def my_int() -> int:
return 1
@asset
def sum_one(my_int: str) -> int: # bug: should be int/float, not str
return len(my_int)
mypy/pyright see two unrelated functions here and report nothing wrong — they have no way to know sum_one's my_int parameter is actually fed by my_int()'s return value. Today the only thing that catches this is Dagster's runtime DagsterType.type_check_fn, which fires during a run, after materialization has already started.
Proposal
Add an opt-out, definition-time validation pass that walks every resolved asset dependency edge and checks the producer's output-type annotation against the consumer's input-type annotation, using the same PEP 484 assignability rules a type checker applies (numeric tower, Optional/Union, generics, subclassing, Any), and respecting whatever strict_optional (mypy) / strictParameterNoneValue (pyright) setting the project already has configured — so it doesn't introduce a third, conflicting set of typing rules. Incompatible edges raise DagsterInvalidDefinitionError as soon as the asset graph is resolved, instead of at runtime.
Why not just rely on mypy/pyright directly?
Because they're blind to this specific class of bug by construction — the connection is name-based, not reference-based, so nothing in the source lets a type checker see across the edge.
Related
#7073 requests strong static typing for resources — same underlying gap (Dagster's dynamic wiring being invisible to static type checkers), different edge of the graph (asset I/O vs. resource injection).
Status
I have a working prototype (toggleable via env var, fails open on ambiguous/unmodelable cases, benchmarked at low-single-digit ms overhead even at thousands of assets, full existing asset-defs test suite passing): pedrovgp#1. Opening this issue first, per the contributing guide's ask to discuss core feature ideas with maintainers before investing further implementation time, and would like feedback on the design before polishing it into a mergeable PR.
What
Dagster wires asset dependencies together by matching a parameter name to an upstream
AssetKeystring, not by an actual Python reference/call:mypy/pyright see two unrelated functions here and report nothing wrong — they have no way to know
sum_one'smy_intparameter is actually fed bymy_int()'s return value. Today the only thing that catches this is Dagster's runtimeDagsterType.type_check_fn, which fires during a run, after materialization has already started.Proposal
Add an opt-out, definition-time validation pass that walks every resolved asset dependency edge and checks the producer's output-type annotation against the consumer's input-type annotation, using the same PEP 484 assignability rules a type checker applies (numeric tower,
Optional/Union, generics, subclassing,Any), and respecting whateverstrict_optional(mypy) /strictParameterNoneValue(pyright) setting the project already has configured — so it doesn't introduce a third, conflicting set of typing rules. Incompatible edges raiseDagsterInvalidDefinitionErroras soon as the asset graph is resolved, instead of at runtime.Why not just rely on mypy/pyright directly?
Because they're blind to this specific class of bug by construction — the connection is name-based, not reference-based, so nothing in the source lets a type checker see across the edge.
Related
#7073 requests strong static typing for resources — same underlying gap (Dagster's dynamic wiring being invisible to static type checkers), different edge of the graph (asset I/O vs. resource injection).
Status
I have a working prototype (toggleable via env var, fails open on ambiguous/unmodelable cases, benchmarked at low-single-digit ms overhead even at thousands of assets, full existing asset-defs test suite passing): pedrovgp#1. Opening this issue first, per the contributing guide's ask to discuss core feature ideas with maintainers before investing further implementation time, and would like feedback on the design before polishing it into a mergeable PR.