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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions