Skip to content

Fix @control(...) overload inferring type[Never] in mypy - #7087

Merged
FeodorFitsner merged 3 commits into
flet-dev:mainfrom
joaoaracheski:fix-control-decorator-overload
Nov 14, 2026
Merged

FeodorFitsner merged 3 commits into
flet-dev:mainfrom
joaoaracheski:fix-control-decorator-overload

Conversation

@joaoaracheski

@joaoaracheski joaoaracheski commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes #7085.

The second overload of control (used for @control(...) with arguments) typed dart_widget_name as Optional[Union[type[T], str]]. When a string is passed, T only appears in the return type and stays unbound, so mypy solves it as Never and reports:

error: Argument 1 has incompatible type "type[MyControl]"; expected "type[Never]"  [arg-type]

This PR narrows that parameter to Optional[str]. The bare @control case (a class passed directly) is already handled by the first overload, so nothing changes at runtime and the implementation signature stays the same.

Test code

import flet as ft
from flet.controls.base_control import control


@control("MyControl")
class MyControl(ft.Control):
    pass


@control
class Plain(ft.Control):
    pass


@control("Iso", isolated=True)
class Iso(ft.Control):
    pass


reveal_type(MyControl)
reveal_type(Plain)
reveal_type(Iso)

mypy before: type[Never] errors on MyControl and Iso.
mypy after: Success: no issues found, and all three are revealed as their own class.
pyright: no errors before or after (it already resolved these correctly).

Also added test_control_args_overload_accepts_only_str_name to test_base_control.py (checks the overload via typing.get_overloads, skipped on Python 3.10); it fails without the fix and passes with it.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I signed the CLA.
  • I have performed a self-review of my own code.
  • My code follows the style guidelines of this project.
  • I have commented my code, particularly in hard-to-understand areas.
  • My changes generate no new warnings.
  • New and existing tests pass locally with my changes.
  • I have made corresponding documentation changes, if applicable.
  • I have added changelog entries for user-facing changes, if applicable.
  • I have updated release guide pages and website/sidebars.yml for breaking changes, removals, and deprecations, if applicable.

Additional details

uv run --group test pytest packages/flet/tests: 507 passed, 8 skipped. ruff check and ruff format --check are clean on the changed files.

This touches the same file as #7084 but different lines, so they don't conflict except for both appending a test at the end of test_base_control.py; I'll rebase whichever lands second.

Changelog suggestion, under Bug fixes:

  • Fix mypy inferring type[Never] for classes decorated with @control("Name", ...) (#7085) by @joaoaracheski.

Summary by Sourcery

Correct the @control(...) overload so mypy preserves the decorated class type instead of inferring type[Never]. креп

Bug Fixes:

  • Fix mypy type inference for classes decorated with argument-based @control(...) usage by restricting the overload’s widget name parameter to strings.

Tests:

  • Add coverage verifying that the argument-based control overload accepts only an optional string widget name.

Fixes flet-dev#7085. The overload for @control(...) accepted type[T] as dart_widget_name, so a call with a string left T unbound and mypy inferred the returned decorator as Callable[[type[Never]], type[Never]]. The bare @control case is already covered by the first overload.
Copilot AI balanced review requested due to automatic review settings November 13, 2026 23:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@ndonkoHenri ndonkoHenri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Please add a changelog entry.

@FeodorFitsner
FeodorFitsner merged commit 379bd92 into flet-dev:main Nov 14, 2026
76 of 104 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: mypy reports type[Never] when @control is used with a widget name, e.g. @control("MyControl")

4 participants