Discourage and deprecate typing.AnyStr
· Issue #105578 · python/cpython (original) (raw)
Feature or enhancement
We should discourage and deprecate typing.AnyStr
.
Pitch
typing.AnyStr
is bad for many reasons:
- The name implies that it has something to do with the type
Any
. It has nothing to do with the typeAny
. - The name implies that it means "any string". It does not mean "any string".
AnyStr
is aTypeVar
, but the name does not follow the common naming convention for TypeVars (using a "T" suffix). Many users appear to think that it is equivalent tostr | bytes
, which is incorrect.AnyStr
is the only type variable that is publicly exported from thetyping
module. Unusually, it is a constrained type variable. Constrained type variables are usually not what users want for modern APIs. Bound type variables, in general, have more intuitive semantics than constrained type variables.- One of the motivations for PEP-695 (accepted by the Steering Council, and now implemented) was the fact that reusable type variables can be confusing in terms of their scope. In general, I believe the consensus of the typing community is that using PEP-695 syntax for creating type variables clarifies the scope of type variables and makes them more intuitive for users. As such, we should discourage using reusable TypeVars such as
AnyStr
.
For all of these reasons, AnyStr
is very commonly misused, especially by typing beginners. We get many PRs at typeshed that misuse AnyStr
, and it can often be hard to catch these misuses in CI (careful manual review is required).
Therefore, we should discourage and deprecate typing.AnyStr
. Unfortunately, it is very widely used, so the deprecation period will have to be a long one.
I propose the following plan:
- Clarify the docs for
typing.AnyStr
. Explain more clearly the differences betweenAnyStr
and a union; give examples of uses ofAnyStr
that would be invalid. This docs clarification can be backported to 3.12 and 3.11. - In Python 3.13, state in the docs that using
AnyStr
is deprecated and that users are encouraged to use PEP-695 syntax wherever possible. - In Python 3.16, remove
AnyStr
fromtyping.__all__
, and start emitting aDeprecationWarning
if a user doesfrom typing import AnyStr
or accessestyping.AnyStr
.
Removing it from__all__
will be a breaking change, but it's the only way to emit aDeprecationWarning
fortyping.AnyStr
before removing it unless we're okay with emitting aDeprecationWarning
any time a user doesfrom typing import *
(and I'm not). - In Python 3.18, remove
AnyStr
from thetyping
module.
Thoughts?