@@ -139,6 +139,7 @@ def python_type_to_typescript_nodes(root_py_type: object) -> TypeScriptNodeTrans
139139
140140 declared_types : OrderedDict [object , TopLevelDeclarationNode | None ] = OrderedDict ()
141141 undeclared_types : OrderedDict [object , object ] = OrderedDict ({root_py_type : root_py_type }) # just a set, really
142+ used_names : dict [str , type | TypeAliasType ] = {}
142143 errors : list [str ] = []
143144
144145 def skip_annotations (py_type : object ) -> object :
@@ -226,7 +227,7 @@ def convert_to_type_node(py_type: object) -> TypeNode:
226227 if key_type_arg is not NumberTypeReferenceNode :
227228 key_type_arg = StringTypeReferenceNode
228229 return TypeReferenceNode (IdentifierNode ("Record" ), [key_type_arg , value_type_arg ])
229-
230+
230231 if origin is tuple :
231232 # Note that when the type is `tuple[()]`,
232233 # `type_args` will be an empty tuple.
@@ -246,9 +247,9 @@ def convert_to_type_node(py_type: object) -> TypeNode:
246247 f"The tuple type '{ py_type } ' is ill-formed because the ellipsis (...) cannot be the first element."
247248 )
248249 return ArrayTypeNode (AnyTypeReferenceNode )
249-
250+
250251 return ArrayTypeNode (convert_to_type_node (type_args [0 ]))
251-
252+
252253 return TupleTypeNode ([convert_to_type_node (py_type_arg ) for py_type_arg in type_args ])
253254
254255 if origin is Union or origin is UnionType :
@@ -272,7 +273,7 @@ def convert_to_type_node(py_type: object) -> TypeNode:
272273
273274 errors .append (f"'{ py_type } ' cannot be used as a type annotation." )
274275 return AnyTypeReferenceNode
275-
276+
276277 def declare_property (name : str , py_annotation : type | TypeAliasType , is_typeddict_attribute : bool , optionality_default : bool ):
277278 """
278279 Declare a property for a given type.
@@ -315,6 +316,13 @@ def declare_property(name: str, py_annotation: type | TypeAliasType, is_typeddic
315316 type_annotation = convert_to_type_node (skip_annotations (current_annotation ))
316317 return PropertyDeclarationNode (name , optional , comment or "" , type_annotation )
317318
319+ def reserve_name (val : type | TypeAliasType ):
320+ type_name = val .__name__
321+ if type_name in used_names :
322+ errors .append (f"Cannot create a schema using two types with the same name. { type_name } conflicts between { val } and { used_names [type_name ]} " )
323+ else :
324+ used_names [type_name ] = val
325+
318326 def declare_type (py_type : object ):
319327 if (is_typeddict (py_type ) or is_dataclass (py_type )) and isinstance (py_type , type ):
320328 comment = py_type .__doc__ or ""
@@ -368,13 +376,19 @@ def declare_type(py_type: object):
368376 prop = declare_property (attr_name , type_hint , is_typeddict_attribute = False , optionality_default = optional )
369377 properties .append (prop )
370378
379+ reserve_name (py_type )
371380 return InterfaceDeclarationNode (py_type .__name__ , type_params , comment , bases , properties )
372381 if isinstance (py_type , type ):
373- errors .append ("Currently only TypedDict, dataclass, and type alias declarations are supported in TypeChat." )
374- return InterfaceDeclarationNode (py_type .__name__ , None , f"Comment for { py_type .__name__ } ." , None , [])
382+ errors .append (f"{ py_type .__name__ } was not a TypedDict, dataclass, or type alias, and cannot be translated." )
383+
384+ reserve_name (py_type )
385+
386+ return InterfaceDeclarationNode (py_type .__name__ , None , "" , None , [])
375387 if isinstance (py_type , TypeAliasType ):
376388 type_params = [TypeParameterDeclarationNode (type_param .__name__ ) for type_param in py_type .__type_params__ ]
377389
390+ reserve_name (py_type )
391+
378392 return TypeAliasDeclarationNode (
379393 py_type .__name__ ,
380394 type_params ,
0 commit comments