11from __future__ import annotations
2+ import sys
23
34from collections import abc
45from collections .abc import Collection , Mapping
6+ import typing
57from typing import (
68 Any ,
79 AnyStr ,
1416 _SpecialForm , # pyright: ignore[reportPrivateUsage]
1517)
1618
19+ import typing_extensions
1720from typing_extensions import Annotated , NotRequired , Required , get_args , get_origin
1821from typing_extensions import Literal as ExtensionsLiteral
1922
@@ -204,6 +207,19 @@ def is_variadic_tuple(self) -> bool:
204207 """
205208 return self .is_tuple and len (self .args ) == 2 and self .args [1 ] == ... # pyright: ignore
206209
210+ if sys .version_info < (3 , 12 ):
211+ @property
212+ def is_type_alias (self ) -> bool :
213+ """Whether the annotation is a new-style `type Type = ...` alias or not.
214+ """
215+ return _is_typing_extensins_type_alias (self )
216+ else :
217+ @property
218+ def is_type_alias (self ) -> bool :
219+ """Whether the annotation is a new-style `type Type = ...` alias or not.
220+ """
221+ return isinstance (self .annotation , typing .TypeAliasType ) or _is_typing_extensins_type_alias (self )
222+
207223 @property
208224 def safe_generic_origin (self ) -> Any :
209225 """A type, safe to be used as a generic type across all supported Python versions.
@@ -260,6 +276,8 @@ def is_subclass_of(self, typ: Any | tuple[Any, ...], /) -> bool:
260276 return isinstance (self .fallback_origin , type ) and issubclass (self .fallback_origin , typ )
261277
262278 def strip_optional (self ) -> TypeView [Any ]:
279+ """Remove the "Optional" component of an `Optional[T]` or `Union[T, None]` type.
280+ """
263281 if not self .is_optional :
264282 return self
265283
@@ -269,3 +287,21 @@ def strip_optional(self) -> TypeView[Any]:
269287 args = tuple (a for a in self .args if a is not NoneType )
270288 non_optional = Union [args ] # type: ignore[valid-type]
271289 return TypeView (non_optional )
290+
291+ def strip_type_alias (self ) -> TypeView [Any ]:
292+ """Remove the type alias from a `type Type = T` type alias.
293+
294+ Examples:
295+ >>> type Foo = int
296+ >>> TypeAlias(Foo).strip_type_alias()
297+ TypeView(int)
298+ """
299+ if not self .is_type_alias :
300+ return self
301+ return TypeView (self .annotation .__value__ )
302+
303+
304+ def _is_typing_extensins_type_alias (type_view : TypeView [Any ]) -> bool :
305+ if hasattr (typing_extensions , "TypeAliasType" ):
306+ return isinstance (type_view .annotation , typing_extensions .TypeAliasType )
307+ return False
0 commit comments