I have written a function string_prompt
to return a type annotation which I have to reuse a lot in the context of typer. This is a working example (run with python -m
):
from typing import Annotated
import typer
app = typer.Typer()
def string_prompt(prompt: bool | str = True):
return Annotated[str, typer.Option(prompt=prompt)]
@app.command()
def public(name: string_prompt(), project_number: string_prompt()):
print(f"You called public with {name}, {project_number}")
if __name__ == "__main__":
app()
This code works, but mypy shows the error:
Invalid type comment or annotation (valid-type). Suggestion: use string_prompt[...] instead of string_prompt(...)
I've tried using square brackets instead, which obviously returns a syntax error, since I can't use square brackets to call a function.
Now my question is: Is there a different way I should declare this function to make mypy understand what I am trying to achieve? I had a look at the documentation of the mypy error, in which it explains, that functions are not a valid type, but the solution proposed which uses Callable
is not applicable in my case, since I want to actually use the return value of the function called.
This is not exactly what you wanted, but you can avoid type annotations getting overly long with type aliases.
For Python <= 3.11:
from typing import TypeAlias
string_prompt: TypeAlias = Annotated[str, typer.Option(prompt=True)]
@app.command()
def public(name: string_prompt, project_number: string_prompt) -> None:
print(f"You called public with {name}, {project_number}")
For Python 3.12+:
type string_prompt = Annotated[str, typer.Option(prompt=True)]
@app.command()
def public(name: string_prompt, project_number: string_prompt) -> None:
print(f"You called public with {name}, {project_number}")
The main limitation here is that you cannot pass arguments to string_prompt
and thus cannot use another value for prompt
. You could do that with "arguments" that are types, for example:
# Python <= 3.11
from typing import TypeAlias, TypeVar
T = TypeVar('T')
prompt: TypeAlias = Annotated[T, typer.Option(prompt=True)]
# Python 3.12+
type prompt[T] = Annotated[T, typer.Option(prompt=True)]
... but the second argument to Annotated
is a runtime value, ignored by type checkers and thus can't be parameterised by type checkers.