Skip to content

Annotate decorated functions #412

@sixolet

Description

@sixolet

When you declare a function, your signature annotation serves three purposes.

  • It allows a program to typecheck the body of the function, finding human errors
  • It allows a program to typecheck the call sites of the function, finding more human errors
  • It allows a human to quickly understand the usage of the function, preventing human errors.

Please excuse my poorly-motivated example below.

from typing import TypeVar, Callable, Dict, Any

T = TypeVar('T')

def reprify(f: Callable[[T], Any]) -> Callable[[T], str]:
    def res(__x: T) -> str:
        return repr(f(__x))
    return res

@reprify
def nonsense(i: int) -> Dict[str, int]:
    return {"nonsense": i}

s = nonsense(3)
reveal_type(s)  # E: Revealed type is 'builtins.str'

The first two purposes are served. The computer can typecheck the body of the function, understanding that it is to return a dictionary inside. The computer can also typecheck the call site of the function, understanding that the decorator causes the function to return a string.

The last purpose is not served. To understand how to use the nonsense function, a human must look at the signature of nonsense, then remember to look at the signature of reprify, and then perform a type calculation in their head combining the two.

I would like a way to optionally make a description of the type of nonsense a call site sees, so the humans do not get confused. We can then tell a computer to check against the decorators.

One possibility, provided for its straw-person properties:

...

@reprify  # type: (int) -> str
def nonsense(i: int) -> Dict[str, int]:
    return {"nonsense": i}

...

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: featureDiscussions about new features for Python's type annotations

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions