From f38327e27301c38ab1457bfcfd620dacabe9e851 Mon Sep 17 00:00:00 2001 From: Netanel-MCE <109151575+netanel-mce@users.noreply.github.com> Date: Fri, 25 Aug 2023 01:55:08 +0300 Subject: [PATCH] Correct schema for mapped object with other keys (#567) * allow-extra-props-where-pattern-properties-not-empty * object mapped and other keys * docs * remove unnecessary changes * remove unnecessary changes 2 * remove unnecessary changes 3 * remove unnecessary changes 4 * fix auto test * fix comment * 0.60.0 * Back to 0.59.0 --------- Co-authored-by: netanel-mce --- api.md | 11 ++++++++++ test/programs/numeric-keys-and-others/main.ts | 5 +++++ .../numeric-keys-and-others/schema.json | 22 +++++++++++++++++++ test/schema.test.ts | 1 + typescript-json-schema.ts | 13 +++++++---- 5 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 test/programs/numeric-keys-and-others/main.ts create mode 100644 test/programs/numeric-keys-and-others/schema.json diff --git a/api.md b/api.md index 57c9d7c9..bb47b106 100644 --- a/api.md +++ b/api.md @@ -1285,6 +1285,17 @@ interface SomeOtherDefinition { ``` +## [numeric-keys-and-others](./test/programs/numeric-keys-and-others) + +```ts +interface NumericKeysAndOthers { + [key: number]: number; + a: string; + b: boolean; +} +``` + + ## [object-numeric-index](./test/programs/object-numeric-index) ```ts diff --git a/test/programs/numeric-keys-and-others/main.ts b/test/programs/numeric-keys-and-others/main.ts new file mode 100644 index 00000000..d668aaad --- /dev/null +++ b/test/programs/numeric-keys-and-others/main.ts @@ -0,0 +1,5 @@ +interface NumericKeysAndOthers { + [key: number]: number; + a: string; + b: boolean; +} diff --git a/test/programs/numeric-keys-and-others/schema.json b/test/programs/numeric-keys-and-others/schema.json new file mode 100644 index 00000000..96b0c0a3 --- /dev/null +++ b/test/programs/numeric-keys-and-others/schema.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "patternProperties": { + "^[0-9]+$": { + "type": "number" + } + }, + "properties": { + "a": { + "type": "string" + }, + "b": { + "type": "boolean" + } + }, + "required": [ + "a", + "b" + ], + "type": "object" +} \ No newline at end of file diff --git a/test/schema.test.ts b/test/schema.test.ts index 226e43d8..dc1f4e86 100644 --- a/test/schema.test.ts +++ b/test/schema.test.ts @@ -379,6 +379,7 @@ describe("schema", () => { assertSchema("array-empty", "MyEmptyArray"); assertSchema("map-types", "MyObject"); assertSchema("extra-properties", "MyObject"); + assertSchema("numeric-keys-and-others", "NumericKeysAndOthers"); }); describe("string literals", () => { diff --git a/typescript-json-schema.ts b/typescript-json-schema.ts index 910df4ce..8d1212b8 100644 --- a/typescript-json-schema.ts +++ b/typescript-json-schema.ts @@ -721,6 +721,9 @@ export class JsonSchemaGenerator { definition.patternProperties = { [NUMERIC_INDEX_PATTERN]: this.getTypeDefinition(arrayType), }; + if (!!Array.from((propertyType).members)?.find((member: [string]) => member[0] !== "__index")) { + this.getClassDefinition(propertyType, definition); + } } else { definition.type = "array"; if (!definition.items) { @@ -1079,8 +1082,8 @@ export class JsonSchemaGenerator { } const indexSymbol: ts.Symbol = (indexSignature.parameters[0]).symbol; const indexType = this.tc.getTypeOfSymbolAtLocation(indexSymbol, node); - const isStringIndexed = indexType.flags === ts.TypeFlags.String; - if (indexType.flags !== ts.TypeFlags.Number && !isStringIndexed) { + const isIndexedObject = indexType.flags === ts.TypeFlags.String || indexType.flags === ts.TypeFlags.Number; + if (indexType.flags !== ts.TypeFlags.Number && !isIndexedObject) { throw new Error( "Not supported: IndexSignatureDeclaration with index symbol other than a number or a string" ); @@ -1105,9 +1108,11 @@ export class JsonSchemaGenerator { if (!def) { def = this.getTypeDefinition(typ, undefined, "anyOf"); } - if (isStringIndexed) { + if (isIndexedObject) { definition.type = "object"; - definition.additionalProperties = def; + if (!Object.keys(definition.patternProperties || {}).length) { + definition.additionalProperties = def; + } } else { definition.type = "array"; if (!definition.items) {