Skip to content

Improve enforced type coverage in CI #1857

@tamird

Description

@tamird

The SDK already runs mypy in CI, but much of the public surface is still only partially annotated. I would like to improve type coverage in a way that is enforced by CI, with priority on the APIs consumers interact with directly.

The main goal is not to make a large mechanical annotation-only change. It is to tighten the type contract incrementally while preserving runtime behavior and avoiding broad escape hatches such as Any, cast, or type: ignore/attribute hacks where a real type can be expressed.

Proposed direction:

  1. Start with consumer-facing modules where annotations provide the most value:

    • Web API clients and responses, sync and async
    • Webhook clients and responses
    • public error types
    • model serialization helpers used to build Slack API payloads
  2. Add a small shared JSON type vocabulary for payload-like values, for example:

    • JSONScalar = Optional[Union[str, int, float, bool]]
    • JSONDict = Dict[str, JSONValue]
    • JSONList = List[JSONValue]
    • JSONValue = Union[JSONScalar, JSONDict, JSONList]

    This gives model serialization and request-building code something more precise than raw dict/Any, while still matching the JSON-ish data the SDK sends and receives.

  3. Tighten CI in stages rather than flipping full strict = true immediately. A practical first step could enable checks that are useful and relatively low-risk across the current package, such as:

    • check_untyped_defs = true
    • warn_return_any = true
    • warn_redundant_casts = true
    • warn_unused_configs = true
    • strict_equality = true
    • disallow_subclassing_any = true
    • no_implicit_reexport = true
    • enable_error_code = "ignore-without-code"
  4. Enable disallow_untyped_defs first for selected public/consumer-facing modules. After that is green, expand the list module-by-module instead of adding a large unprincipled exclusion list.

  5. Keep any remaining exclusions explicit and temporary. For example, if SCIM or legacy RTM need separate treatment, that should be called out as a known follow-up rather than hidden behind a broad ignore block.

  6. Continue to use the existing project workflow:

    • update canonical Web client sources, not generated files directly
    • run codegen for generated Web clients
    • validate with the existing mypy/lint/test scripts

Open questions for maintainers:

  • Is this type-hardening direction welcome for this repository?
  • Which public modules should be prioritized first?
  • Are there areas, such as legacy RTM or SCIM, that maintainers would prefer to leave out of the initial pass?
  • Is adding shared JSON payload aliases acceptable, or would you prefer a different naming/location for those types?

Category (place an x in each of the [ ])

  • slack_sdk.web.WebClient (sync/async) (Web API client)
  • slack_sdk.webhook.WebhookClient (sync/async) (Incoming Webhook, response_url sender)
  • slack_sdk.models (UI component builders)
  • slack_sdk.oauth (OAuth Flow Utilities)
  • slack_sdk.socket_mode (Socket Mode client)
  • slack_sdk.audit_logs (Audit Logs API client)
  • slack_sdk.scim (SCIM API client)
  • slack_sdk.rtm (RTM client)
  • slack_sdk.signature (Request Signature Verifier)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions