Skip to content

Commit 68b756e

Browse files
committed
Add prefixItems support
1 parent 36afb3e commit 68b756e

File tree

4 files changed

+36
-40
lines changed

4 files changed

+36
-40
lines changed

.changeset/soft-mugs-guess.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-typescript": minor
3+
---
4+
5+
Add prefixItems support

packages/openapi-typescript/src/transform/schema-object.ts

+9-11
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,16 @@ export function defaultSchemaObjectTransform(schemaObject: SchemaObject | Refere
9191
indentLv++;
9292
let itemType = "unknown";
9393
let isTupleType = false;
94-
if (schemaObject.items) {
95-
if (Array.isArray(schemaObject.items)) {
96-
// tuple type support
97-
isTupleType = true;
98-
const result: string[] = [];
99-
schemaObject.items.forEach((item) => {
100-
result.push(transformSchemaObject(item, { path, ctx: { ...ctx, indentLv } }));
101-
});
102-
itemType = `[${result.join(",")}]`;
103-
} else {
104-
itemType = transformSchemaObject(schemaObject.items, { path, ctx: { ...ctx, indentLv } });
94+
if (schemaObject.prefixItems || Array.isArray(schemaObject.items)) {
95+
// tuple type support
96+
isTupleType = true;
97+
const result: string[] = [];
98+
for (const item of schemaObject.prefixItems ?? (schemaObject.items as (SchemaObject | ReferenceObject)[])) {
99+
result.push(transformSchemaObject(item, { path, ctx: { ...ctx, indentLv } }));
105100
}
101+
itemType = `[${result.join(", ")}]`;
102+
} else if (schemaObject.items) {
103+
itemType = transformSchemaObject(schemaObject.items, { path, ctx: { ...ctx, indentLv } });
106104
}
107105
const minItems: number = typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
108106
const maxItems: number | undefined = typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && minItems <= schemaObject.maxItems ? schemaObject.maxItems : undefined;

packages/openapi-typescript/src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ export type SchemaObject = {
438438
| { type: "integer"; minimum?: number; maximum?: number }
439439
| {
440440
type: "array";
441-
prefixItems?: SchemaObject | ReferenceObject;
441+
prefixItems?: (SchemaObject | ReferenceObject)[];
442442
items?: SchemaObject | ReferenceObject | (SchemaObject | ReferenceObject)[];
443443
minItems?: number;
444444
maxItems?: number;

packages/openapi-typescript/test/schema-object.test.ts

+21-28
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ describe("Schema Object", () => {
111111
});
112112

113113
test("tuple array", () => {
114-
const schema: SchemaObject = { type: "array", items: [{ type: "string" },{"type": "number"}],minItems:2,maxItems:2 };
114+
const schema: SchemaObject = { type: "array", items: [{ type: "string" }, { type: "number" }], minItems: 2, maxItems: 2 };
115115
const generated = transformSchemaObject(schema, options);
116-
expect(generated).toBe("[string,number]");
116+
expect(generated).toBe("[string, number]");
117117
});
118118

119119
test("ref", () => {
@@ -279,10 +279,7 @@ describe("Schema Object", () => {
279279
});
280280

281281
test("enum + polymorphism + nullable", () => {
282-
const generated = transformSchemaObject(
283-
{ type: ["string", "null"], enum: ["", "false positive", "won't fix", "used in tests"] },
284-
options
285-
);
282+
const generated = transformSchemaObject({ type: ["string", "null"], enum: ["", "false positive", "won't fix", "used in tests"] }, options);
286283
expect(generated).toBe(`"" | "false positive" | "won't fix" | "used in tests" | null`);
287284
});
288285
});
@@ -341,10 +338,7 @@ describe("Schema Object", () => {
341338
test("discriminator", () => {
342339
const schema: SchemaObject = {
343340
type: "object",
344-
allOf: [
345-
{ $ref: 'components["schemas"]["parent"]' },
346-
{ type: "object", properties: { string: { type: "string" } } },
347-
],
341+
allOf: [{ $ref: 'components["schemas"]["parent"]' }, { type: "object", properties: { string: { type: "string" } } }],
348342
};
349343
const generated = transformSchemaObject(schema, {
350344
path: options.path,
@@ -370,10 +364,7 @@ describe("Schema Object", () => {
370364
test("discriminator escape", () => {
371365
const schema: SchemaObject = {
372366
type: "object",
373-
allOf: [
374-
{ $ref: 'components["schemas"]["parent"]' },
375-
{ type: "object", properties: { string: { type: "string" } } },
376-
],
367+
allOf: [{ $ref: 'components["schemas"]["parent"]' }, { type: "object", properties: { string: { type: "string" } } }],
377368
};
378369
const generated = transformSchemaObject(schema, {
379370
path: options.path,
@@ -532,20 +523,22 @@ describe("Schema Object", () => {
532523
});
533524
});
534525

535-
describe("supportArrayLength", () => {
536-
test("true", () => {
537-
const opts = { ...options, ctx: { ...options.ctx, supportArrayLength: true } };
538-
expect(transformSchemaObject({ type: "array", items: { type: "string" } }, options)).toBe(`(string)[]`);
539-
expect(transformSchemaObject({ type: "array", items: { type: "string" }, minItems: 1 }, opts)).toBe(
540-
`[string, ...(string)[]]`
541-
);
542-
expect(transformSchemaObject({ type: "array", items: { type: "string" }, maxItems: 2 }, opts)).toBe(
543-
`[] | [string] | [string, string]`
544-
);
545-
expect(transformSchemaObject({ type: "array", items: { type: "string" }, maxItems: 20 }, opts)).toBe(
546-
`(string)[]`
547-
);
548-
});
526+
test("supportArrayLength", () => {
527+
const opts = { ...options, ctx: { ...options.ctx, supportArrayLength: true } };
528+
expect(transformSchemaObject({ type: "array", items: { type: "string" } }, options)).toBe(`(string)[]`);
529+
expect(transformSchemaObject({ type: "array", items: { type: "string" }, minItems: 1 }, opts)).toBe(`[string, ...(string)[]]`);
530+
expect(transformSchemaObject({ type: "array", items: { type: "string" }, maxItems: 2 }, opts)).toBe(`[] | [string] | [string, string]`);
531+
expect(transformSchemaObject({ type: "array", items: { type: "string" }, maxItems: 20 }, opts)).toBe(`(string)[]`);
532+
});
533+
534+
test("prefixItems", () => {
535+
const schema: SchemaObject = {
536+
type: "array",
537+
items: { type: "number" },
538+
prefixItems: [{ type: "number" }, { type: "number" }, { type: "number" }],
539+
};
540+
const generated = transformSchemaObject(schema, options);
541+
expect(generated).toBe(`[number, number, number]`);
549542
});
550543

551544
describe("immutableTypes", () => {

0 commit comments

Comments
 (0)