diff --git a/examples/petstore-v2.ts b/examples/petstore-v2.ts index 944102b..a851cc2 100644 --- a/examples/petstore-v2.ts +++ b/examples/petstore-v2.ts @@ -148,7 +148,7 @@ export class ApiClient { store = { getInventory: () => { - return this.Fetch("get", "/store/inventory", {}) + return this.Fetch>("get", "/store/inventory", {}) }, placeOrder: (body: Order) => { diff --git a/examples/petstore-v3.ts b/examples/petstore-v3.ts index 7c61e94..3fafa61 100644 --- a/examples/petstore-v3.ts +++ b/examples/petstore-v3.ts @@ -141,7 +141,7 @@ export class ApiClient { store = { getInventory: () => { - return this.Fetch("get", "/store/inventory", {}) + return this.Fetch>("get", "/store/inventory", {}) }, placeOrder: (body: Order) => { diff --git a/src/type-gen.ts b/src/type-gen.ts index 31d8a66..fccdf56 100644 --- a/src/type-gen.ts +++ b/src/type-gen.ts @@ -1,6 +1,6 @@ import { Oas3Schema, Referenced } from "@redocly/openapi-core/lib/typings/openapi" import { filterEmpty } from "array-utils-ts" -import { isArray, uniq, upperFirst } from "lodash-es" +import { isArray, isBoolean, uniq, upperFirst } from "lodash-es" import ts from "typescript" import { Context } from "./config" import { OAS3, unref } from "./schema" @@ -68,6 +68,19 @@ const makeInlineEnum = (s: OAS3) => { return undefined } +const makeObject = (ctx: Context, s: OAS3): ts.TypeNode => { + if (s.type !== "object") throw new Error(`makeObject: not an object ${JSON.stringify(s)}`) + + if (s.additionalProperties && !isBoolean(s.additionalProperties)) { + return f.createTypeReferenceNode("Record", [ + f.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), + makeType(ctx, s.additionalProperties), + ]) + } + + return f.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword) +} + export const makeType = (ctx: Context, s?: Referenced): ts.TypeNode => { const mk = makeType.bind(null, ctx) @@ -123,7 +136,7 @@ export const makeType = (ctx: Context, s?: Referenced): ts.TypeNode => { let t: ts.TypeNode // if (s.type === "object") t = f.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword) - if (s.type === "object") t = f.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword) + if (s.type === "object") t = makeObject(ctx, s) else if (s.type === "boolean") t = f.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword) else if (s.type === "number") t = f.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword) else if (s.type === "string") t = f.createKeywordTypeNode(ts.SyntaxKind.StringKeyword) diff --git a/test/type-gen.test.ts b/test/type-gen.test.ts index 7c06b71..59a3e3f 100644 --- a/test/type-gen.test.ts +++ b/test/type-gen.test.ts @@ -117,6 +117,19 @@ test("type inline", async () => { { type: "object", properties: { a: { type: "string" } }, additionalProperties: true }, "{ a?: string }", ) + + t({ type: "object", additionalProperties: { type: "number" } }, "Record") + + t( + { + type: "object", + additionalProperties: { + type: "array", + items: { oneOf: [{ type: "string" }, { type: "number" }] }, + }, + }, + "Record", + ) }) test("type alias", async () => {