@@ -192,26 +192,50 @@ const tsFlagToPgTypeMap: Record<number, string> = {
192192 [ ts . TypeFlags . BigIntLiteral ] : "bigint" ,
193193} ;
194194
195- function getPgTypeFromTsTypeUnion ( params : { types : ts . Type [ ] } ) : E . Either < string , PgTypeStrategy > {
196- const types = params . types . filter ( ( t ) => ( t . flags & ts . TypeFlags . Null ) === 0 ) ;
197- const isStringLiterals = types . every ( ( t ) => t . flags & ts . TypeFlags . StringLiteral ) ;
195+ function getPgTypeFromTsTypeUnion ( params : {
196+ types : ts . Type [ ] ;
197+ checker : ts . TypeChecker ;
198+ options : RuleOptionConnection ;
199+ } ) : E . Either < string , PgTypeStrategy | null > {
200+ const { types, checker, options } = params ;
201+ const nonNullTypes = types . filter ( ( t ) => ( t . flags & ts . TypeFlags . Null ) === 0 ) ;
202+
203+ if ( nonNullTypes . length === 0 ) {
204+ return E . right ( null ) ;
205+ }
206+
207+ const isStringLiterals = nonNullTypes . every ( ( t ) => t . flags & ts . TypeFlags . StringLiteral ) ;
198208
199209 if ( isStringLiterals ) {
200210 return E . right ( {
201211 kind : "one-of" ,
202- types : types . map ( ( t ) => ( t as ts . StringLiteralType ) . value ) ,
212+ types : nonNullTypes . map ( ( t ) => ( t as ts . StringLiteralType ) . value ) ,
203213 cast : "text" ,
204214 } ) ;
205215 }
206216
207- const isUnionOfTheSameType = types . every ( ( t ) => t . flags === types [ 0 ] . flags ) ;
208- const pgType = getPgTypeFromFlags ( types [ 0 ] . flags ) ;
217+ const results = nonNullTypes . map ( ( t ) => checkType ( { checker , type : t , options } ) ) ;
218+ const firstResult = results [ 0 ] ;
209219
210- if ( ! isUnionOfTheSameType || pgType === undefined ) {
211- return E . left ( createMixedTypesInUnionErrorMessage ( types . map ( ( t ) => t . flags ) ) ) ;
220+ if ( E . isLeft ( firstResult ) ) {
221+ return firstResult ;
212222 }
213223
214- return E . right ( { kind : "cast" , cast : pgType } ) ;
224+ const firstPgType = firstResult . right ;
225+
226+ for ( let i = 1 ; i < results . length ; i ++ ) {
227+ const result = results [ i ] ;
228+ if ( E . isLeft ( result ) ) {
229+ return result ;
230+ }
231+
232+ const pgType = result . right ;
233+ if ( pgType . cast !== firstPgType . cast ) {
234+ return E . left ( createMixedTypesInUnionErrorMessage ( nonNullTypes . map ( ( t ) => t . flags ) ) ) ;
235+ }
236+ }
237+
238+ return E . right ( { kind : "cast" , cast : firstPgType . cast } ) ;
215239}
216240
217241type PgTypeStrategy =
@@ -273,21 +297,17 @@ function getPgTypeFromTsType(params: {
273297 }
274298
275299 if ( symbolType . isUnion ( ) ) {
276- // If union is X | null, continue with X
277- const nonNullTypes = symbolType . types . filter ( ( t ) => ( t . flags & ts . TypeFlags . Null ) === 0 ) ;
278- if ( nonNullTypes . length === 1 ) {
279- return checkType ( { checker, type : nonNullTypes [ 0 ] , options } ) ;
280- }
281-
282- return getPgTypeFromTsTypeUnion ( { types : symbolType . types } ) ;
300+ return getPgTypeFromTsTypeUnion ( { types : symbolType . types , checker, options } ) ;
283301 }
284302
285303 if ( TSUtils . isTsArrayUnionType ( checker , symbolType ) ) {
286304 const elementTypeUnion = symbolType . resolvedTypeArguments ?. [ 0 ] . types ;
287305 return elementTypeUnion
288306 ? pipe (
289- getPgTypeFromTsTypeUnion ( { types : elementTypeUnion } ) ,
290- E . map ( ( pgType ) => ( { kind : "cast" , cast : `${ pgType . cast } []` } ) ) ,
307+ getPgTypeFromTsTypeUnion ( { types : elementTypeUnion , checker, options } ) ,
308+ E . map ( ( pgType ) =>
309+ pgType === null ? null : { kind : "cast" , cast : `${ pgType . cast } []` } ,
310+ ) ,
291311 )
292312 : E . left ( "Invalid array union type" ) ;
293313 }
@@ -327,22 +347,7 @@ function getPgTypeFromTsType(params: {
327347
328348 // Handle union types
329349 if ( type . isUnion ( ) ) {
330- const matchingType = type . types . find ( ( t ) => {
331- const flags = getPgTypeFromFlags ( t . flags ) ;
332- return flags !== undefined && flags !== null ;
333- } ) ;
334-
335- if ( matchingType ) {
336- return E . right ( { kind : "cast" , cast : getPgTypeFromFlags ( matchingType . flags ) ! } ) ;
337- }
338-
339- // If union is X | null, continue with X
340- const nonNullTypes = type . types . filter ( ( t ) => ( t . flags & ts . TypeFlags . Null ) === 0 ) ;
341- if ( nonNullTypes . length === 1 ) {
342- return checkType ( { checker, type : nonNullTypes [ 0 ] , options } ) ;
343- }
344-
345- return E . left ( "Unsupported union type" ) ;
350+ return getPgTypeFromTsTypeUnion ( { types : type . types , checker, options } ) ;
346351 }
347352
348353 return checkType ( { checker, type, options } ) ;
@@ -437,22 +442,12 @@ function checkType(params: {
437442
438443 // Handle union types
439444 if ( type . isUnion ( ) ) {
440- const matchingType = type . types . find ( ( t ) => {
441- const flags = getPgTypeFromFlags ( t . flags ) ;
442- return flags !== undefined && flags !== null ;
443- } ) ;
444-
445- if ( matchingType ) {
446- return E . right ( { kind : "cast" , cast : getPgTypeFromFlags ( matchingType . flags ) ! } ) ;
447- }
448-
449- // If union is X | null, continue with X
450- const nonNullTypes = type . types . filter ( ( t ) => ( t . flags & ts . TypeFlags . Null ) === 0 ) ;
451- if ( nonNullTypes . length === 1 ) {
452- return checkType ( { checker, type : nonNullTypes [ 0 ] , options } ) ;
453- }
454-
455- return E . left ( "Unsupported union type" ) ;
445+ return pipe (
446+ getPgTypeFromTsTypeUnion ( { types : type . types , checker, options } ) ,
447+ E . chain ( ( pgType ) =>
448+ pgType === null ? E . left ( "Unsupported union type (only null)" ) : E . right ( pgType ) ,
449+ ) ,
450+ ) ;
456451 }
457452
458453 // Fallback for unsupported types
0 commit comments