@@ -131,24 +131,31 @@ export type CheckMatchingArrayTypes<Result, NewResult> =
131
131
132
132
type Simplify < T > = T extends object ? { [ K in keyof T ] : T [ K ] } : T
133
133
134
- type MergeDeep < New , Row > = {
135
- [ K in keyof New | keyof Row ] : K extends keyof New
134
+ // Extract only explicit (non-index-signature) keys.
135
+ type ExplicitKeys < T > = {
136
+ [ K in keyof T ] : string extends K ? never : K
137
+ } [ keyof T ]
138
+
139
+ type MergeExplicit < New , Row > = {
140
+ // We merge all the explicit keys which allows merge and override of types like
141
+ // { [key: string]: unknown } and { someSpecificKey: boolean }
142
+ [ K in ExplicitKeys < New > | ExplicitKeys < Row > ] : K extends keyof New
136
143
? K extends keyof Row
137
144
? Row [ K ] extends SelectQueryError < string >
138
145
? New [ K ]
139
- : // Check if the override is on a embeded relation (array)
146
+ : // Check if the override is on a embedded relation (array)
140
147
New [ K ] extends any [ ]
141
148
? Row [ K ] extends any [ ]
142
149
? Array < Simplify < MergeDeep < NonNullable < New [ K ] [ number ] > , NonNullable < Row [ K ] [ number ] > > > >
143
150
: New [ K ]
144
- : // Check if both properties are objects omiting a potential null union
151
+ : // Check if both properties are objects omitting a potential null union
145
152
IsPlainObject < NonNullable < New [ K ] > > extends true
146
153
? IsPlainObject < NonNullable < Row [ K ] > > extends true
147
154
? // If they are, use the new override as source of truth for the optionality
148
155
ContainsNull < New [ K ] > extends true
149
- ? // If the override want to preserve optionality
156
+ ? // If the override wants to preserve optionality
150
157
Simplify < MergeDeep < NonNullable < New [ K ] > , NonNullable < Row [ K ] > > > | null
151
- : // If the override want to enforce non-null result
158
+ : // If the override wants to enforce non-null result
152
159
Simplify < MergeDeep < New [ K ] , NonNullable < Row [ K ] > > >
153
160
: New [ K ] // Override with New type if Row isn't an object
154
161
: New [ K ] // Override primitives with New type
@@ -158,6 +165,15 @@ type MergeDeep<New, Row> = {
158
165
: never
159
166
}
160
167
168
+ type MergeDeep < New , Row > = Simplify <
169
+ MergeExplicit < New , Row > &
170
+ // Intersection here is to restore dynamic keys into the merging result
171
+ // eg:
172
+ // {[key: number]: string}
173
+ // or Record<string, number | null>
174
+ ( string extends keyof Row ? { [ K : string ] : Row [ string ] } : { } )
175
+ >
176
+
161
177
// Helper to check if a type is a plain object (not an array)
162
178
type IsPlainObject < T > = T extends any [ ] ? false : T extends object ? true : false
163
179
0 commit comments