diff --git a/src/parser.ts b/src/parser.ts index 50f29b9e..4b50a98f 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -20,6 +20,7 @@ import { isPrimitive, JSONSchema as LinkedJSONSchema, JSONSchemaWithDefinitions, + NormalizedJSONSchema, SchemaSchema, SchemaType } from './types/JSONSchema' @@ -313,9 +314,19 @@ function newInterface( usedNames: UsedNames, keyName?: string, keyNameFromDefinition?: string -): TInterface { +): TInterface | TIntersection { + let complexAdditionalProperties: false | NormalizedJSONSchema + + if (schema.additionalProperties !== undefined && typeof schema.additionalProperties !== 'boolean') { + complexAdditionalProperties = schema.additionalProperties + schema.additionalProperties = false + } else { + complexAdditionalProperties = false + } + const name = standaloneName(schema, keyNameFromDefinition, usedNames)! - return { + + const parsedInterface: TInterface = { comment: schema.description, keyName, params: parseSchema(schema, options, processed, usedNames, name), @@ -323,6 +334,43 @@ function newInterface( superTypes: parseSuperTypes(schema, options, processed, usedNames), type: 'INTERFACE' } + + if (complexAdditionalProperties === false) { + return parsedInterface + } else { + const parsedAdditionalProperties: TInterface = { + params: [ + { + ast: parse(complexAdditionalProperties, options, '[k: string]', processed, usedNames), + isPatternProperty: false, + isRequired: true, + isUnreachableDefinition: false, + keyName: '[k: string]' + } + ], + superTypes: [], + type: 'INTERFACE' + } + + if (parsedInterface.params.length > 0) { + delete parsedInterface.standaloneName + return { + comment: schema.description, + keyName, + standaloneName: name, + params: [parsedInterface, parsedAdditionalProperties], + type: 'INTERSECTION' + } + } else { + // there were only additionalProperties + return { + ...parsedAdditionalProperties, + comment: schema.description, + keyName, + standaloneName: name + } + } + } } function parseSuperTypes( diff --git a/test/__snapshots__/test/test.ts.md b/test/__snapshots__/test/test.ts.md index d9e34739..43a0e5e2 100644 --- a/test/__snapshots__/test/test.ts.md +++ b/test/__snapshots__/test/test.ts.md @@ -115,10 +115,11 @@ Generated by [AVA](https://avajs.dev). * and run json-schema-to-typescript to regenerate this file.␊ */␊ ␊ - export interface AdditionalProperties {␊ + export type AdditionalProperties = {␊ foo?: string;␊ + } & {␊ [k: string]: number;␊ - }␊ + };␊ ` ## additionalProperties.2.js @@ -1271,6 +1272,15 @@ Generated by [AVA](https://avajs.dev). [k: string]: unknown;␊ };␊ export type Header1 = ExampleXORExamples & SchemaXORContent;␊ + export type Callback = {␊ + /**␊ + * This interface was referenced by \`Callback\`'s JSON-Schema definition␊ + * via the \`patternProperty\` "^x-".␊ + */␊ + [k: string]: unknown;␊ + } & {␊ + [k: string]: PathItem;␊ + };␊ export type SecurityScheme =␊ | APIKeySecurityScheme␊ | HTTPSecurityScheme␊ @@ -1579,9 +1589,6 @@ Generated by [AVA](https://avajs.dev). */␊ [k: string]: unknown;␊ }␊ - export interface Callback {␊ - [k: string]: PathItem;␊ - }␊ export interface Components {␊ schemas?: {␊ /**␊ @@ -2132,10 +2139,11 @@ Generated by [AVA](https://avajs.dev). * and run json-schema-to-typescript to regenerate this file.␊ */␊ ␊ - export interface StrictIndexSignatures {␊ + export type StrictIndexSignatures = {␊ maybe?: string;␊ + } & {␊ [k: string]: string | undefined;␊ - }␊ + };␊ ` ## options.style.js @@ -2326,15 +2334,16 @@ Generated by [AVA](https://avajs.dev). * and run json-schema-to-typescript to regenerate this file.␊ */␊ ␊ + export type Parent = {␊ + [k: string]: StringChild;␊ + } & {␊ + [k: string]: number;␊ + };␊ /**␊ * This interface was referenced by \`Parent\`'s JSON-Schema definition␊ * via the \`patternProperty\` "^[a-zA-Z]+".␊ */␊ export type StringChild = string;␊ - ␊ - export interface Parent {␊ - [k: string]: number;␊ - }␊ ` ## realWorld.awsQuicksight.js @@ -444063,6 +444072,15 @@ Generated by [AVA](https://avajs.dev). [k: string]: unknown;␊ };␊ export type Header1 = ExampleXORExamples & SchemaXORContent;␊ + export type Callback = {␊ + /**␊ + * This interface was referenced by \`Callback\`'s JSON-Schema definition␊ + * via the \`patternProperty\` "^x-".␊ + */␊ + [k: string]: unknown;␊ + } & {␊ + [k: string]: PathItem;␊ + };␊ export type SecurityScheme =␊ | APIKeySecurityScheme␊ | HTTPSecurityScheme␊ @@ -444371,9 +444389,6 @@ Generated by [AVA](https://avajs.dev). */␊ [k: string]: unknown;␊ }␊ - export interface Callback {␊ - [k: string]: PathItem;␊ - }␊ export interface Components {␊ schemas?: {␊ /**␊ @@ -447709,6 +447724,7 @@ Generated by [AVA](https://avajs.dev). prerestart?: ScriptsRestart;␊ restart?: ScriptsRestart;␊ postrestart?: ScriptsRestart;␊ + } & {␊ [k: string]: string | undefined;␊ };␊ /**␊ @@ -447749,6 +447765,7 @@ Generated by [AVA](https://avajs.dev). };␊ engines?: {␊ node?: string;␊ + } & {␊ [k: string]: string;␊ };␊ engineStrict?: boolean;␊ @@ -447789,11 +447806,12 @@ Generated by [AVA](https://avajs.dev). */␊ esnext?:␊ | string␊ - | {␊ + | ({␊ main?: string;␊ browser?: string;␊ + } & {␊ [k: string]: string;␊ - };␊ + });␊ /**␊ * Allows packages within a directory to depend on one another using direct linking of local files. Additionally, dependencies within a workspace are hoisted to the workspace root when possible to reduce duplication. Note: It's also a good idea to set "private" to true when using this feature.␊ */␊ @@ -448598,6 +448616,7 @@ Generated by [AVA](https://avajs.dev). company?: {␊ name: string;␊ };␊ + } & {␊ [k: string]: KString;␊ };␊ [k: string]: unknown;␊ diff --git a/test/__snapshots__/test/test.ts.snap b/test/__snapshots__/test/test.ts.snap index cd1fb9ed..6b793eb3 100644 Binary files a/test/__snapshots__/test/test.ts.snap and b/test/__snapshots__/test/test.ts.snap differ