Skip to content

False "Invalid index type" for min derived from return type #14664

Closed

Description

@ods

Bug Report

Mypy gives [index] error for key when calling min from function that is declared to return Optional.

To Reproduce

This pretty valid

def func() -> Optional[int]:
    d = {1: 2, 3: 4}
    return min([1, 2], key=lambda k: d[k], default=None)

returns error

Invalid index type "Optional[int]" for "Dict[int, int]"; expected type "int"  [index]

Changing default to 0 doesn't fix the problem, but changing return type of func to int does. So, the following works fine:

def func() -> int:
    d = {1: 2, 3: 4}
    return min([1, 2], key=lambda k: d[k], default=0)

Expected Behavior

No error for the first example, as default is never compared to objects in collection.

Actual Behavior

Invalid index type "Optional[int]" for "Dict[int, int]"; expected type "int"  [index]

Your Environment

  • Mypy version used: 1.0.0
  • Mypy command-line flags: no
  • Mypy configuration options from mypy.ini (and other config files): no
  • Python version used: 3.10

Activity

  1. added
    bugmypy got something wrong
    on Feb 9, 2023
  2. EdwardEisenhauer commented on Feb 20, 2023

    @EdwardEisenhauer

    I experienced a similar issue with the following code:

    from typing import Optional
    
    
    class MyObject:
        def __init__(self, attribute: int) -> None:
            self.attribute = attribute
    
    
    def find_biggest_attribute(objects: list[MyObject]) -> Optional[MyObject]:
        return max(objects, default=None, key=lambda object: object.attribute)
    
    
    print(find_biggest_attribute([MyObject(42), MyObject(41)]))
    
    print(find_biggest_attribute([]))

    Running mypy raises:

    mypy_bug.py:10: error: Item "None" of "Optional[MyObject]" has no attribute "attribute"  [union-attr]
            return max(objects, default=None, key=lambda object: object.attribute)
                                                                 ^~~~~~~~~~~~~~~~
    Found 1 error in 1 file (checked 1 source file)

    As per Python built-in max() documentation:

    The default argument specifies an object to return if the provided iterable is empty. If the iterable is empty and default is not provided, a ValueError is raised.

  3. EugeneYushin commented on Feb 21, 2025

    @EugeneYushin

    Know what:

    def func() -> Optional[int]:
        d = {1: 2, 3: 4}
        x = min([1, 2], key=lambda k: d[k], default=None)
        return x
    
    # mypy.....................................................................Passed

    This is odd

  4. added a commit that references this issue on May 15, 2025
    a0307b5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-type-contextType context / bidirectional inference

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions