This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: allow typing.cast with TYPE_CHECKING
Type: behavior Stage: resolved
Components: Versions: Python 3.9
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: dpinol, gvanrossum, kj, levkivskyi
Priority: normal Keywords:

Created on 2020-11-16 19:43 by dpinol, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (2)
msg381147 - (view) Author: Daniel Pinyol (dpinol) Date: 2020-11-16 19:50
Executing the following code we get this error on the "cast" call
NameError: name 'A' is not defined

from __future__ import annotations
from typing import TYPE_CHECKING, Optional, cast
   class A:

def f(a: A):

f(cast(A, "anything"))

It would be nice that you could use "cast" to force casts when the symbol is only available during TYPE_CHECKING. According to the "cast" specs, cast only works during type checking, but not during runtime. Hence, I think would be desirable that this code was legal. thanks

This returns the value unchanged. To the type checker this signals that the return value has the designated type, but at runtime we intentionally don’t check anything (we want this to be as fast as possible).
msg385119 - (view) Author: Ken Jin (kj) * (Python committer) Date: 2021-01-15 17:05
Sorry, I don't think this is a typing module issue.

The NameError stems from what you mentioned: 'A' not being defined since TYPE_CHECKING evaluates to false at runtime. This would raise an error in any Python code, not just typing. The equivalent is this::

>>> A
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'A' is not defined

Without the future import, def f(a: A): ... already throws that NameError. The reason why it works in your example is because 'A' isn't evaluated at function declaration time with the future import.

To appease your static type checker and not cause runtime errors, you might want to try:

f(cast("A", "anything"))

Which seems to work in mypy and pycharm. (Sorry, I don't have pyre/pytype/pyright to check with, though I would be surprised if this didn't pass on them.)

Please correct me if you feel anything I wrote was incorrect :).
Date User Action Args
2022-04-11 14:59:38adminsetgithub: 86543
2021-02-09 02:02:39gvanrossumsetstatus: open -> closed
resolution: not a bug
stage: resolved
2021-01-15 17:05:35kjsetnosy: + gvanrossum, levkivskyi, kj
messages: + msg385119
2020-11-16 19:50:37dpinolsetmessages: + msg381147
2020-11-16 19:43:56dpinolcreate