The following try_parse method takes as input a value of type T and a series of functions with input type T. The functions do not necessarily have to have the same output type, e.g., it could be int, float, MyCustomClass etc. How would I appropriately annotate the function type in this code?
T = TypeVar("T")
U = TypeVar("U")
def try_parse(value: T, *parse_functions: Callable[[T], U]) -> U:
for parse_function in parse_functions:
try:
return parse_function(value)
except ValueError:
pass
raise ValueError(f"Cannot parse {value} with any of {parse_functions}")
One way to annotate your
try_parsemethod, assuming you want to keep the code flexible but still benefit from type checking to some extent, is to type parse_functions as a sequence of callables where each callable takes an input of typeTand returns a value of typeAny. This approach sacrifices some type specificity for flexibility:Anyis used for the return type ofparse_functionsand the return type oftry_parseitself, indicating that the function can return any type, which aligns with your requirement thatparse_functionscould have varying output types. While this approach reduces the benefits of static type checking by introducingAny, it reflects the dynamic nature of yourtry_parsefunction more accurately.If you're working in a context where you can guarantee that all functions in parse_functions will return the same type, or if you're okay with enforcing that constraint, you could stick with the original annotation using U as the return type. However, based on your description, it seems like using Any is closer to your intention for this function.