No errors reported for obviously wrong code

There are several common reasons why obviously wrong code is notflagged as an error.

  • The function containing the error is not annotated. Functions thatdo not have any annotations (neither for any argument nor for thereturn type) are not type-checked, and even the most blatant typeerrors (e.g. 2 + 'a') pass silently. The solution is to addannotations. Where that isn’t possible, functions without annotationscan be checked using —check-untyped-defs.

Example:

  1. def foo(a):
  2. return '(' + a.split() + ')' # No error!

This gives no error even though a.split() is “obviously” a list(the author probably meant a.strip()). The error is reportedonce you add annotations:

  1. def foo(a: str) -> str:
  2. return '(' + a.split() + ')'
  3. # error: Unsupported operand types for + ("str" and List[str])

If you don’t know what types to add, you can use Any, but beware:

  • One of the values involved has type ‘Any’. Extending the aboveexample, if we were to leave out the annotation for a, we’d getno error:
  1. def foo(a) -> str:
  2. return '(' + a.split() + ')' # No error!

The reason is that if the type of a is unknown, the type ofa.split() is also unknown, so it is inferred as having typeAny, and it is no error to add a string to an Any.

If you’re having trouble debugging such situations,reveal_type() might come in handy.

Note that sometimes library stubs have imprecise type information,e.g. the pow() builtin returns Any (see typeshed issue 285 for the reason).

  • :py:meth:__init__ <object.__init__> method has no annotatedarguments or return type annotation. initis considered fully-annotated if at least one argument is annotated,while mypy will infer the return type as None.The implication is that, for a init methodthat has no argument, you’ll have to explicitly annotate the return typeas None to type-check this init method:
  1. def foo(s: str) -> str:
  2. return s
  3.  
  4. class A():
  5. def __init__(self, value: str): # Return type inferred as None, considered as typed method
  6. self.value = value
  7. foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str"
  8.  
  9. class B():
  10. def __init__(self): # No argument is annotated, considered as untyped method
  11. foo(1) # No error!
  12.  
  13. class C():
  14. def __init__(self) -> None: # Must specify return type to type-check
  15. foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str"
  1. def foo() -> str:
  2. return None # No error!

You may have disabled strict optional checking (seeDisabling strict optional checking for more).