Thanks, now I get why you feel like the type system is fighting your style of programming.
> all of those options are unnecessary busy work for what should be a few simple lines of code
If you re-type your variable often, then how do you make sure you’re really keeping track of all those types?
If you re-type it only a few times, then I’m not entirely convinced that declaring a few additional variables really constitutes busywork.
Small example with additional variables instead of re-typing the same variable:
# pylint: disable=disallowed-name, missing-function-docstring, missing-module-docstring, redefined-outer-name
from typing import NewType
NEEDS_CHECKING = True
NotCleaned = NewType("NotCleaned", str)
Checked = NewType("Checked", str)
Cleaned = NewType("Cleaned", str)
original_foo = ["SOME ", "dirty ", " Data"]
annotated_foo = [NotCleaned(item) for item in original_foo]
cleaned_foo = [
Cleaned(item.lower().strip().replace("dirty", "tidy"))
for item in annotated_foo
]
foo: list[Checked | Cleaned]
if NEEDS_CHECKING:
for idx, item in enumerate(cleaned_foo):
if item and (item[0] == " " or item[-1] == " "):
raise RuntimeError(f"Whitespace found in item #{idx}: {item=}")
if "dirt" in item:
raise RuntimeError(f"Item #{idx} is dirty: {item=}")
foo = [Checked(item) for item in cleaned_foo]
else:
foo = list(cleaned_foo)
print(foo)
# => ['some', 'tidy', 'data']
This survives strict type checking (`mypy --strict`). I don’t feel that renaming the variables introduces much noise or busywork here? One might argue that renaming even adds clarity?