Skip to content

Should have a way to annotate an Optional carryover method. #3295

Closed
@euresti

Description

@euresti

Edited with a better example.

Let's suppose you have a function that can take an Optional and returns something based on that or None if it's None.

from typing import overload, Optional

def bar(foo: Optional[int]) -> Optional[str]:
   if foo is None:
       return None
   else:
       return str(foo)

x = None  # type: Optional[int]

reveal_type(bar(None))  # Line 18
reveal_type(bar(x))
reveal_type(bar('foo'))

There's one problem with this being annotated this way. If you pass a Non-Optional you get returned an Optional[str] even though it's not possible. So I thought the new @overload stuff might help here but it doesn't:

from typing import overload, Optional

@overload
def bar(foo: int) -> str:
    ...

@overload
def bar(foo: Optional[int]) -> Optional[str]:
    ...

def bar(foo: Optional[int]) -> Optional[str]:
   if foo is None:
       return None
   else:
       return str(foo)

x = None  # type: Optional[int]

reveal_type(bar(None))
reveal_type(bar(x))
reveal_type(bar('foo'))

Sadly that gives me an error and the wrong types:

tt.py:4: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
tt.py:19: error: Revealed type is 'Union[builtins.int, builtins.None]'
tt.py:20: error: Revealed type is 'Any'
tt.py:21: error: Revealed type is 'Any'

I also tried None as the argument to the 2nd overload. That got me closer:

tt.py:19: error: Revealed type is 'Union[builtins.int, builtins.None]'
tt.py:20: error: Revealed type is 'Any'
tt.py:21: error: Revealed type is 'builtins.str'

I would love to be able to specify this as it would make a lot of our code easier to type. Maybe there's a way to do it with a TypeVar but I couldn't figure it out.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions