Skip to content

Commit 29ebad7

Browse files
authored
Merge pull request #1059 from BitGo/dx-2181-fix-empty-object
fix: fix the problem with empty objects in intersections
2 parents 269dada + 713ecab commit 29ebad7

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

packages/openapi-generator/src/optimize.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { combineComments } from './comments';
2-
import { isPrimitive, type Primitive, type Schema } from './ir';
2+
import { isPrimitive, type CombinedType, type Primitive, type Schema } from './ir';
33

44
export type OptimizeFn = (schema: Schema) => Schema;
55

@@ -29,6 +29,28 @@ export function foldIntersection(schema: Schema, optimize: OptimizeFn): Schema {
2929
}
3030
});
3131

32+
// If the combined object is empty (no properties) and result is an intersection,
33+
// we can simplify by removing the empty object
34+
const hasProperties = Object.keys(combinedObject.properties).length > 0;
35+
36+
if (!hasProperties && result !== combinedObject) {
37+
// At this point, result must be an intersection since it was reassigned
38+
const intersectionResult = result as unknown as CombinedType;
39+
40+
// Remove the empty object from the intersection
41+
const nonEmptySchemas = intersectionResult.schemas.filter(
42+
(s: Schema) => !(s.type === 'object' && Object.keys(s.properties).length === 0),
43+
);
44+
45+
if (nonEmptySchemas.length === 0) {
46+
return combinedObject;
47+
} else if (nonEmptySchemas.length === 1) {
48+
return nonEmptySchemas[0]!;
49+
} else {
50+
return { type: 'intersection', schemas: nonEmptySchemas };
51+
}
52+
}
53+
3254
return result;
3355
}
3456

packages/openapi-generator/test/optimize.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,72 @@ test('non-consolidatable unions are not consolidated', () => {
180180

181181
assert.deepEqual(optimize(input), expected);
182182
});
183+
184+
test('intersection with non-object types removes empty object', () => {
185+
const input: Schema = {
186+
type: 'intersection',
187+
schemas: [
188+
{
189+
type: 'object',
190+
properties: {},
191+
required: [],
192+
},
193+
{
194+
type: 'ref',
195+
name: 'SomeType',
196+
location: '/path/to/file.ts',
197+
},
198+
],
199+
};
200+
201+
// The empty object should be removed, leaving just the ref
202+
const expected: Schema = {
203+
type: 'ref',
204+
name: 'SomeType',
205+
location: '/path/to/file.ts',
206+
};
207+
208+
assert.deepEqual(optimize(input), expected);
209+
});
210+
211+
test('intersection with multiple non-object types removes empty object', () => {
212+
const input: Schema = {
213+
type: 'intersection',
214+
schemas: [
215+
{
216+
type: 'object',
217+
properties: {},
218+
required: [],
219+
},
220+
{
221+
type: 'ref',
222+
name: 'TypeA',
223+
location: '/path/to/file.ts',
224+
},
225+
{
226+
type: 'ref',
227+
name: 'TypeB',
228+
location: '/path/to/file.ts',
229+
},
230+
],
231+
};
232+
233+
// The empty object should be removed, leaving the intersection of refs
234+
const expected: Schema = {
235+
type: 'intersection',
236+
schemas: [
237+
{
238+
type: 'ref',
239+
name: 'TypeA',
240+
location: '/path/to/file.ts',
241+
},
242+
{
243+
type: 'ref',
244+
name: 'TypeB',
245+
location: '/path/to/file.ts',
246+
},
247+
],
248+
};
249+
250+
assert.deepEqual(optimize(input), expected);
251+
});

0 commit comments

Comments
 (0)