@@ -34,11 +34,6 @@ export class CommonToolsFormatter implements TypeFormatter {
3434 return true ;
3535 }
3636
37- // Check if this is an Opaque<T> union (T | OpaqueRef<T>)
38- if ( this . isOpaqueUnion ( type , context . typeChecker ) ) {
39- return true ;
40- }
41-
4237 // Check if this is a wrapper type (Cell/Stream/OpaqueRef) via type structure
4338 const wrapperInfo = this . getWrapperTypeInfo ( type ) ;
4439 return wrapperInfo !== undefined ;
@@ -47,26 +42,6 @@ export class CommonToolsFormatter implements TypeFormatter {
4742 formatType ( type : ts . Type , context : GenerationContext ) : SchemaDefinition {
4843 const n = context . typeNode ;
4944
50- // Check if this is an Opaque<T> union and handle it first
51- // This prevents the UnionFormatter from creating an anyOf
52- const opaqueUnionInfo = this . getOpaqueUnionInfo ( type , context . typeChecker ) ;
53- if ( opaqueUnionInfo ) {
54- // Format the base type T and add asOpaque: true
55- const innerSchema = this . schemaGenerator . formatChildType (
56- opaqueUnionInfo . baseType ,
57- context ,
58- undefined , // Don't pass typeNode since we're working with the unwrapped type
59- ) ;
60-
61- // Handle boolean schemas
62- if ( typeof innerSchema === "boolean" ) {
63- return innerSchema === false
64- ? { asOpaque : true , not : true } as SchemaDefinition // false = "no value is valid"
65- : { asOpaque : true } as SchemaDefinition ; // true = "any value is valid"
66- }
67- return { ...innerSchema , asOpaque : true } as SchemaDefinition ;
68- }
69-
7045 // Check via typeNode for all wrapper types (handles both direct usage and aliases)
7146 const resolvedWrapper = n
7247 ? resolveWrapperNode ( n , context . typeChecker )
@@ -216,133 +191,6 @@ export class CommonToolsFormatter implements TypeFormatter {
216191 return { ...innerSchema , [ propertyName ] : true } ;
217192 }
218193
219- /**
220- * Check if a type is an Opaque<T> union (T | OpaqueRef<T>)
221- */
222- private isOpaqueUnion ( type : ts . Type , checker : ts . TypeChecker ) : boolean {
223- return this . getOpaqueUnionInfo ( type , checker ) !== undefined ;
224- }
225-
226- /**
227- * Extract information from an Opaque<T> union type.
228- * Opaque<T> is defined as: T | OpaqueRef<T>
229- * This function detects this pattern and returns the base type T.
230- */
231- private getOpaqueUnionInfo (
232- type : ts . Type ,
233- checker : ts . TypeChecker ,
234- ) : { baseType : ts . Type } | undefined {
235- // Must be a union type
236- if ( ! ( type . flags & ts . TypeFlags . Union ) ) {
237- return undefined ;
238- }
239-
240- const unionType = type as ts . UnionType ;
241- const members = unionType . types ;
242-
243- // Must have exactly 2 members
244- if ( members . length !== 2 ) {
245- return undefined ;
246- }
247-
248- // One member should be OpaqueRef<T>, the other should be T
249- let opaqueRefMember : ts . Type | undefined ;
250- let baseMember : ts . Type | undefined ;
251-
252- for ( const member of members ) {
253- // Check if this member is an OpaqueRef type (it will be an intersection)
254- const isOpaqueRef = this . isOpaqueRefType ( member ) ;
255- if ( isOpaqueRef ) {
256- opaqueRefMember = member ;
257- } else {
258- baseMember = member ;
259- }
260- }
261-
262- // Both members must be present for this to be an Opaque<T> union
263- if ( ! opaqueRefMember || ! baseMember ) {
264- return undefined ;
265- }
266-
267- // Verify that the OpaqueRef's type argument matches the base type
268- // Extract T from OpaqueRef<T>
269- const opaqueRefInnerType = this . extractOpaqueRefTypeArgument (
270- opaqueRefMember ,
271- checker ,
272- ) ;
273- if ( ! opaqueRefInnerType ) {
274- return undefined ;
275- }
276-
277- // The inner type of OpaqueRef should match the base member
278- // Use type equality check
279- const innerTypeString = checker . typeToString ( opaqueRefInnerType ) ;
280- const baseTypeString = checker . typeToString ( baseMember ) ;
281-
282- if ( innerTypeString !== baseTypeString ) {
283- // Not a matching Opaque<T> pattern
284- return undefined ;
285- }
286-
287- return { baseType : baseMember } ;
288- }
289-
290- /**
291- * Check if a type is an OpaqueRef type (intersection with OpaqueRefMethods)
292- */
293- private isOpaqueRefType ( type : ts . Type ) : boolean {
294- // OpaqueRef types are intersection types
295- if ( ! ( type . flags & ts . TypeFlags . Intersection ) ) {
296- return false ;
297- }
298-
299- const intersectionType = type as ts . IntersectionType ;
300- for ( const constituent of intersectionType . types ) {
301- if ( constituent . flags & ts . TypeFlags . Object ) {
302- const objectType = constituent as ts . ObjectType ;
303- if ( objectType . objectFlags & ts . ObjectFlags . Reference ) {
304- const typeRef = objectType as ts . TypeReference ;
305- const name = typeRef . target ?. symbol ?. name ;
306- if ( name === "OpaqueRefMethods" ) {
307- return true ;
308- }
309- }
310- }
311- }
312- return false ;
313- }
314-
315- /**
316- * Extract the type argument T from OpaqueRef<T>
317- */
318- private extractOpaqueRefTypeArgument (
319- type : ts . Type ,
320- checker : ts . TypeChecker ,
321- ) : ts . Type | undefined {
322- if ( ! ( type . flags & ts . TypeFlags . Intersection ) ) {
323- return undefined ;
324- }
325-
326- const intersectionType = type as ts . IntersectionType ;
327- for ( const constituent of intersectionType . types ) {
328- if ( constituent . flags & ts . TypeFlags . Object ) {
329- const objectType = constituent as ts . ObjectType ;
330- if ( objectType . objectFlags & ts . ObjectFlags . Reference ) {
331- const typeRef = objectType as ts . TypeReference ;
332- const name = typeRef . target ?. symbol ?. name ;
333- if ( name === "OpaqueRefMethods" ) {
334- // Found OpaqueRefMethods<T>, extract T
335- const typeArgs = checker . getTypeArguments ( typeRef ) ;
336- if ( typeArgs && typeArgs . length > 0 ) {
337- return typeArgs [ 0 ] ;
338- }
339- }
340- }
341- }
342- }
343- return undefined ;
344- }
345-
346194 /**
347195 * Get wrapper type information (Cell/Stream/OpaqueRef)
348196 * Handles both direct references and intersection types (e.g., OpaqueRef<"literal">)
0 commit comments