pythonpython-typingmypy

How to build a type from another type and make mypy checking work


I'm working with Python's type hinting system and I'm trying to create a type alias for a function that's similar to an existing function type, but with one additional argument. Here's what I've attempted:

from typing import Callable

# Original function type
RK_function = Callable[[float, int], int]

# Attempted new function type with an additional int argument
RK_functionBIS = Callable[[*RK_function.__args__[:-1], int], int]

I expected RK_functionBIS to represent Callable[[float, int, int], int], which it does when runned directly without checking it with mypy. However, when I run mypy for type checking, I get this error: text

error: Invalid type alias: expression is not a valid type [valid-type] Q


Solution

  • As of today, Python doesn't support direct extraction of a Callable alias's arguments for use in another type. However, if your code snippet is representative of the problem you're solving, then your RK_functions look like they're completely made of positional-only parameters, so you can at least refactor out the arguments part. See mypy Playground:

    from collections.abc import Callable
    from typing_extensions import Unpack, TypeAliasType
    
    RK_function_args = TypeAliasType("RK_function_args", tuple[float, int])
    
    # Original function type
    RK_function = TypeAliasType("RK_function", Callable[[Unpack[RK_function_args]], int])
    
    # Attempted new function type with an additional int argument
    RK_functionBIS = TypeAliasType("RK_functionBIS", Callable[[Unpack[RK_function_args], int], int])
    
    >>> bis: RK_functionBIS
    >>> res: int = bis(1.0, 2, 3)  # OK
    >>> bis("1.0", 2, 3)           # Error: first argument should be float
    >>> bis(1.0, 2)                # Error: not enough arguments