diff --git a/src/utils.ts b/src/utils.ts index e17f938fd..01ad9248f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import { OpenAPI2, OpenAPI3 } from "./types"; +import { OpenAPI2, OpenAPI2Reference, OpenAPI2SchemaObject, OpenAPI3 } from "./types"; export function comment(text: string): string { return `/** @@ -121,3 +121,9 @@ export function unrefComponent(components: any, ref: string): any { const [type, object] = ref.match(/(?<=\[")([^"]+)/g) as string[]; return components[type][object]; } + +export function isOpenAPI2Reference( + additionalProperties: OpenAPI2SchemaObject | OpenAPI2Reference | boolean +): additionalProperties is OpenAPI2Reference { + return (additionalProperties as OpenAPI2Reference).$ref !== undefined; +} diff --git a/src/v2.ts b/src/v2.ts index 6bbec80f1..12af30f36 100644 --- a/src/v2.ts +++ b/src/v2.ts @@ -1,6 +1,6 @@ import propertyMapper from "./property-mapper"; -import { OpenAPI2, OpenAPI2SchemaObject, OpenAPI2Schemas, SwaggerToTSOptions } from "./types"; -import { comment, nodeType, transformRef, tsArrayOf, tsIntersectionOf, tsUnionOf } from "./utils"; +import { OpenAPI2, OpenAPI2Reference, OpenAPI2SchemaObject, OpenAPI2Schemas, SwaggerToTSOptions } from "./types"; +import { comment, nodeType, transformRef, tsArrayOf, tsIntersectionOf, tsUnionOf, isOpenAPI2Reference } from "./utils"; export const PRIMITIVES: { [key: string]: "boolean" | "string" | "number" } = { // boolean types @@ -40,6 +40,14 @@ export default function generateTypesV2(input: OpenAPI2 | OpenAPI2Schemas, optio // propertyMapper const propertyMapped = options ? propertyMapper(definitions, options.propertyMapper) : definitions; + //this functionality could perhaps be added to the nodeType function, but I don't want to mess with that code + function getAdditionalPropertiesType(additionalProperties: OpenAPI2SchemaObject | OpenAPI2Reference | boolean) { + if (isOpenAPI2Reference(additionalProperties)) { + return transformRef(additionalProperties.$ref, rawSchema ? "definitions/" : ""); + } + return nodeType(additionalProperties); + } + // type conversions function transform(node: OpenAPI2SchemaObject): string { switch (nodeType(node)) { @@ -67,7 +75,7 @@ export default function generateTypesV2(input: OpenAPI2 | OpenAPI2Schemas, optio // if additional properties, add to end of properties if (node.additionalProperties) { - properties += `[key: string]: ${nodeType(node.additionalProperties) || "any"};\n`; + properties += `[key: string]: ${getAdditionalPropertiesType(node.additionalProperties) || "any"};\n`; } return tsIntersectionOf([ diff --git a/tests/v2/index.test.ts b/tests/v2/index.test.ts index 972fbeb4c..a2fc36039 100644 --- a/tests/v2/index.test.ts +++ b/tests/v2/index.test.ts @@ -255,6 +255,38 @@ describe("transformation", () => { ); }); + it("additionalProperties 2 (issue #345)", () => { + const schema: OpenAPI2 = { + swagger: "2.0", + definitions: { + Messages: { + type: "object", + additionalProperties: { + $ref: "#/definitions/Message", + }, + }, + Message: { + type: "object", + properties: { + code: { + type: "integer", + }, + text: { + type: "string", + }, + }, + }, + }, + }; + expect(swaggerToTS(schema)).toBe( + format(` + export interface definitions { + Messages: { [key: string]: definitions["Message"] } + Message: { code?: number; text?: string } + }`) + ); + }); + it("allOf", () => { const schema: OpenAPI2 = { swagger: "2.0",