@@ -58,7 +58,7 @@ export function createModel(sdkContext: CSharpEmitterContext): [CodeModel, reado
5858 if ( type . kind === "model" ) {
5959 const model = type as InputModelType ;
6060 models . push ( model ) ;
61- existingModelKeys . add ( ` ${ model . namespace } . ${ model . name } ` ) ;
61+ existingModelKeys . add ( typeDedupeKey ( model ) ) ;
6262 } else if ( type . kind === "enum" ) {
6363 enums . push ( type as InputEnumType ) ;
6464 }
@@ -67,20 +67,22 @@ export function createModel(sdkContext: CSharpEmitterContext): [CodeModel, reado
6767 // response models for protocol-only paging operations where TCGC does not include the
6868 // response model in sdkPackage.models, or enums only reachable through nested property
6969 // types of such models). See https://github.com/microsoft/typespec/issues/9391. Dedupe
70- // by namespace + name to avoid duplicates when TCGC produces a different reference for
71- // the same type, while still allowing distinct types that share a name across namespaces.
72- const existingEnumKeys = new Set ( enums . map ( ( e ) => `${ e . namespace } .${ e . name } ` ) ) ;
70+ // by crossLanguageDefinitionId when available, falling back to namespace + name for
71+ // anonymous types (empty crossLanguageDefinitionId). This avoids duplicates when TCGC
72+ // produces a different reference for the same logical type, while still preserving
73+ // distinct types that share a name across different namespaces.
74+ const existingEnumKeys = new Set ( enums . map ( ( e ) => typeDedupeKey ( e ) ) ) ;
7375 for ( const type of sdkContext . __typeCache . types . values ( ) ) {
7476 if ( typesBeforeClients . has ( type ) ) continue ;
7577 if ( type . kind === "model" ) {
7678 const model = type as InputModelType ;
77- const key = ` ${ model . namespace } . ${ model . name } ` ;
79+ const key = typeDedupeKey ( model ) ;
7880 if ( existingModelKeys . has ( key ) ) continue ;
7981 models . push ( model ) ;
8082 existingModelKeys . add ( key ) ;
8183 } else if ( type . kind === "enum" ) {
8284 const enumType = type as InputEnumType ;
83- const key = ` ${ enumType . namespace } . ${ enumType . name } ` ;
85+ const key = typeDedupeKey ( enumType ) ;
8486 if ( existingEnumKeys . has ( key ) ) continue ;
8587 enums . push ( enumType ) ;
8688 existingEnumKeys . add ( key ) ;
@@ -187,6 +189,15 @@ function fixNamingConflicts(models: InputModelType[], constants: InputLiteralTyp
187189 }
188190}
189191
192+ /**
193+ * Returns a dedup key for a model or enum type. Prefers `crossLanguageDefinitionId`
194+ * because it is the canonical identity TCGC assigns. Falls back to `namespace.name`
195+ * for anonymous/constant-derived types whose `crossLanguageDefinitionId` is empty.
196+ */
197+ function typeDedupeKey ( type : InputModelType | InputEnumType ) : string {
198+ return type . crossLanguageDefinitionId || `${ type . namespace } .${ type . name } ` ;
199+ }
200+
190201function navigateModels ( sdkContext : CSharpEmitterContext ) : [ void , readonly Diagnostic [ ] ] {
191202 const diagnostics = createDiagnosticCollector ( ) ;
192203 for ( const m of sdkContext . sdkPackage . models ) {
0 commit comments