typing_extensions icon indicating copy to clipboard operation
typing_extensions copied to clipboard

TypeAliasType not raising TypeError when it is has no parameters

Open Daraan opened this issue 1 year ago • 1 comments

When using a TypeAliasType without type_params it should raise an error which it currently doesn't:

from typing import TypeAliasType as typing_TA
from typing_extensions import TypeAliasType

# this should raise an error
Simple = TypeAliasType("Simple", int)
Simple_typing = typing_TA("Simple", int)
try:
   Simple[str]  # No TypeError
except TypeError:
   print("TypeError raised like expected")
else:
   print("No type error was raised.")  # <-- will be printed

Simple_typing[str] # will raise TypeError

However, currently in 3.12+ when using type_params=() the code unexpectedly allows subscription. See also cpython issue #124498. This issue likely needs an upstream decision first if the following case is intended or a bug:

from typing import TypeAliasType as typing_TA
Simple2 = typing_TA("Simple", int, type_params=())
Simple2[str]  # no type error for typing.TypeAliasType

Also related to

  • partial overlap with #239
  • https://github.com/pydantic/pydantic/issues/6158

Daraan avatar Sep 25 '24 08:09 Daraan

Currently the 3.13.0 typing.TypeAliasType variant passes the following tests:

    def test_subscription_without_type_params(self):
        Simple = TypeAliasType("Simple", int)
        with self.assertRaises(TypeError, msg="Only generic type aliases are subscriptable"):
            Simple[int]
        with self.assertRaises(TypeError, msg="Only generic type aliases are subscriptable"):
            Simple[[]]
        with self.assertRaises(TypeError, msg="Only generic type aliases are subscriptable"):
            Simple[()]
       
        # A TypeVar in the value does not allow subscription
        T = TypeVar('T')
        MissingTypeParamsErr = TypeAliasType("MissingTypeParamsErr", List[T])
        self.assertEqual(MissingTypeParamsErr.__type_params__, ())
        self.assertEqual(MissingTypeParamsErr.__parameters__, ())
        with self.assertRaises(TypeError, msg="Only generic type aliases are subscriptable"):
            MissingTypeParamsErr[int]
        with self.assertRaises(TypeError, msg="Only generic type aliases are subscriptable"):
            MissingTypeParamsErr[[]]
        with self.assertRaises(TypeError, msg="Only generic type aliases are subscriptable"):
            MissingTypeParamsErr[()]
            
        # However, providing type_params=() argument allows subscription
        MissingTypeParams = TypeAliasType("MissingTypeParams", List[T], type_params=())
        self.assertEqual(MissingTypeParams.__type_params__, ())
        self.assertEqual(MissingTypeParams.__parameters__, ())
        # These do not raise
        MissingTypeParams[int]
        MissingTypeParams[[]]
        MissingTypeParams[()]
        # These do not raise
        Simple2 = TypeAliasType("Simple2", int, type_params=())
        Simple2[int]
        Simple2[[]]
        Simple2[()]

EDIT: This behavior has now been changed and errors are raised like expected. #473 will align the behavior with the latest cpython implementation.

Daraan avatar Sep 25 '24 08:09 Daraan