diff --git a/basedtyping/__init__.py b/basedtyping/__init__.py index 1ec8a0a..a5d8431 100644 --- a/basedtyping/__init__.py +++ b/basedtyping/__init__.py @@ -51,6 +51,8 @@ "Untyped", "Intersection", "TypeForm", + "In", + "Out", ) if TYPE_CHECKING: @@ -556,3 +558,46 @@ def f[T](t: TypeForm[T]) -> T: ... reveal_type(f(int | str)) # int | str """) + + +class _InForm(_BasedSpecialForm, _root=True): # type: ignore[misc] + def __init__(self, doc: str): + self._name = "In" + self._doc = self.__doc__ = doc + + def __getitem__(self, parameters: object | tuple[object]) -> _BasedGenericAlias: + if not isinstance(parameters, tuple): + parameters = (parameters,) + + return _BasedGenericAlias(self, parameters) # type: ignore[arg-type] + + +In = _InForm(doc="""\ + A type that can be used to represent a contravariant form of a type. + For example: + + list_of_objects: list[object] + list_of_ints: list[In[int]] = list_of_objects # valid + """) + + +class _OutForm(_BasedSpecialForm, _root=True): # type: ignore[misc] + def __init__(self, doc: str): + self._name = "Out" + self._doc = self.__doc__ = doc + + def __getitem__(self, parameters: object | tuple[object]) -> _BasedGenericAlias: + if not isinstance(parameters, tuple): + parameters = (parameters,) + + return _BasedGenericAlias(self, parameters) # type: ignore[arg-type] + + +Out = _OutForm(doc="""\ + An annotation that can be used to represent a covariant form of a type. + For example: + + list_of_ints: list[int] + list_of_objects: list[Out[object]] = a # valid + """) + diff --git a/tests/test_in_out.py b/tests/test_in_out.py new file mode 100644 index 0000000..a623ce9 --- /dev/null +++ b/tests/test_in_out.py @@ -0,0 +1 @@ +raise NotImplementedError \ No newline at end of file