Proposal: Add ty type checking to api/ #21963

Open
opened 2026-02-21 20:15:03 -05:00 by yindo · 1 comment
Owner

Originally created by @BeautyyuYanli on GitHub (Jan 28, 2026).

Originally assigned to: @BeautyyuYanli on GitHub.

Summary

Propose adding ty as an additional Python type checker for the api/ codebase, rolled out incrementally so it is safe to adopt and easy to review.

Key points:

  • Run via uv: cd api && uv run ty check
  • Land in small PRs, grouped by dependency order (A1 → A2 → B → C → D → E) to avoid big-bang changes.
  • When narrowing is required, prefer runtime validation (isinstance, Pydantic BaseModel / TypeAdapter) over cast().

Motivation

The api/ layer touches many dynamic boundaries (request payloads, workflow graphs, external SDKs). ty provides another static check that can catch issues earlier and keep types consistent, but adopting it all-at-once would be disruptive.

This proposal introduces ty in a way that:

  • doesn’t block developers on day 1
  • provides a clear, reviewable path to increase coverage
  • encourages safer runtime validation at boundaries (where static typing is inherently limited)

Proposed rollout (each item is a PR)

PR0 (bootstrap): enable ty but exclude everything

Goal: Make make type-check pass trivially while introducing the tool + wiring.

Changes:

  • Add api/ty.toml with [src].exclude covering all api/ production code paths (effectively a no-op check initially).
  • Update the root Makefile so make type-check includes ty (e.g. runs cd api && uv run ty check).
  • (Optional) Add a CI step that runs make type-check to ensure consistency.

Acceptance:

  • make type-check passes immediately after PR0.
  • No developer workflow disruption.

PR A1: foundational typing/contracts

Scope (examples): protocol boundaries, provider plumbing, low-level helpers.

Changes:

  • Unexclude only the A1 paths from api/ty.toml.
  • Fix ty errors with runtime checks where needed.

Acceptance:

  • cd api && uv run ty check passes.

PR A2: workflow engine & nodes

Scope: workflow execution, graph runtime, node factory, node implementations.

Changes:

  • Unexclude A2 paths.
  • Replace unsafe assumptions with runtime validation.

Acceptance:

  • ty check passes.

PR B: prompt + app runtime boundaries

Scope: prompt transforms and app runner boundaries.

Acceptance:

  • ty check passes.

PR C: services/controllers/fields/libs

Scope: request/service layers where untyped dict/list payloads enter.

Acceptance:

  • ty check passes.

PR D: observability + integrations

Scope: tracing + external integrations where upstream packages may be partially typed.

Acceptance:

  • ty check passes.

PR E: vector DB integrations (external services)

Scope: VDB adapters (Elastic/Milvus/Tencent/Weaviate/AnalyticDB/etc.).

Acceptance:

  • ty check passes.

Fixing guidelines (important)

When satisfying ty:

  • Prefer runtime type checking over cast():
    • isinstance(...) for unions/object values
    • pydantic.TypeAdapter(...).validate_python(...) for untrusted structures
    • BaseModel.model_validate(...) for dict → model
  • Avoid widening types just to satisfy the checker unless the runtime reality is truly wider.

End state

  • api/ty.toml exclusions shrink from “everything” to only true non-production/generated paths (e.g. migrations/, tests/), or near-zero.
  • make type-check consistently runs both basedpyright (current) and ty.
Originally created by @BeautyyuYanli on GitHub (Jan 28, 2026). Originally assigned to: @BeautyyuYanli on GitHub. ## Summary Propose adding **`ty`** as an additional Python type checker for the `api/` codebase, rolled out incrementally so it is safe to adopt and easy to review. Key points: - Run via `uv`: `cd api && uv run ty check` - Land in small PRs, grouped by dependency order (**A1 → A2 → B → C → D → E**) to avoid big-bang changes. - When narrowing is required, prefer **runtime validation** (`isinstance`, Pydantic `BaseModel` / `TypeAdapter`) over `cast()`. ## Motivation The `api/` layer touches many dynamic boundaries (request payloads, workflow graphs, external SDKs). `ty` provides another static check that can catch issues earlier and keep types consistent, but adopting it all-at-once would be disruptive. This proposal introduces `ty` in a way that: - doesn’t block developers on day 1 - provides a clear, reviewable path to increase coverage - encourages safer runtime validation at boundaries (where static typing is inherently limited) ## Proposed rollout (each item is a PR) ### PR0 (bootstrap): enable `ty` but exclude everything **Goal:** Make `make type-check` pass trivially while introducing the tool + wiring. Changes: - Add `api/ty.toml` with `[src].exclude` covering all `api/` production code paths (effectively a no-op check initially). - Update the root `Makefile` so **`make type-check`** includes `ty` (e.g. runs `cd api && uv run ty check`). - (Optional) Add a CI step that runs `make type-check` to ensure consistency. Acceptance: - `make type-check` passes immediately after PR0. - No developer workflow disruption. ### PR A1: foundational typing/contracts Scope (examples): protocol boundaries, provider plumbing, low-level helpers. Changes: - Unexclude only the A1 paths from `api/ty.toml`. - Fix `ty` errors with runtime checks where needed. Acceptance: - `cd api && uv run ty check` passes. ### PR A2: workflow engine & nodes Scope: workflow execution, graph runtime, node factory, node implementations. Changes: - Unexclude A2 paths. - Replace unsafe assumptions with runtime validation. Acceptance: - `ty check` passes. ### PR B: prompt + app runtime boundaries Scope: prompt transforms and app runner boundaries. Acceptance: - `ty check` passes. ### PR C: services/controllers/fields/libs Scope: request/service layers where untyped dict/list payloads enter. Acceptance: - `ty check` passes. ### PR D: observability + integrations Scope: tracing + external integrations where upstream packages may be partially typed. Acceptance: - `ty check` passes. ### PR E: vector DB integrations (external services) Scope: VDB adapters (Elastic/Milvus/Tencent/Weaviate/AnalyticDB/etc.). Acceptance: - `ty check` passes. ## Fixing guidelines (important) When satisfying `ty`: - Prefer **runtime type checking** over `cast()`: - `isinstance(...)` for unions/`object` values - `pydantic.TypeAdapter(...).validate_python(...)` for untrusted structures - `BaseModel.model_validate(...)` for dict → model - Avoid widening types just to satisfy the checker unless the runtime reality is truly wider. ## End state - `api/ty.toml` exclusions shrink from “everything” to only true non-production/generated paths (e.g. `migrations/`, `tests/`), or near-zero. - `make type-check` consistently runs both basedpyright (current) and `ty`.
yindo added the 💪 enhancementProposalpython:uv labels 2026-02-21 20:15:03 -05:00
Author
Owner

@BeautyyuYanli commented on GitHub (Jan 29, 2026):

Opened PR #31721 (api: reduce ty excludes for A1) from BeautyyuYanli:yanli/remove-ty-a1.

@BeautyyuYanli commented on GitHub (Jan 29, 2026): Opened PR #31721 (api: reduce ty excludes for A1) from BeautyyuYanli:yanli/remove-ty-a1.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#21963