diff --git a/src/generators/typescript/TypeScriptRenderer.ts b/src/generators/typescript/TypeScriptRenderer.ts index d083fe6d82..7808dbfdd7 100644 --- a/src/generators/typescript/TypeScriptRenderer.ts +++ b/src/generators/typescript/TypeScriptRenderer.ts @@ -107,6 +107,14 @@ ${lines.map(line => ` * ${line}`).join('\n')} content.push(additionalProperty); } + if (this.model.patternProperties !== undefined) { + for (const [pattern, patternModel] of Object.entries(this.model.patternProperties)) { + const propertyName = getUniquePropertyName(this.model, `${pattern}${DefaultPropertyNames.patternProperties}`); + const renderedPatternProperty = await this.runPropertyPreset(propertyName, patternModel, PropertyType.patternProperties); + content.push(renderedPatternProperty); + } + } + return this.renderBlock(content); } @@ -118,6 +126,7 @@ ${lines.map(line => ` * ${line}`).join('\n')} signature = this.renderTypeSignature(property, { isRequired: this.model.isRequired(propertyName) }); return `${name}${signature};`; case PropertyType.additionalProperty: + case PropertyType.patternProperties: signature = this.renderType(property); return `${name}?: Map;`; default: diff --git a/src/generators/typescript/renderers/ClassRenderer.ts b/src/generators/typescript/renderers/ClassRenderer.ts index 2ace927f63..01e649bd40 100644 --- a/src/generators/typescript/renderers/ClassRenderer.ts +++ b/src/generators/typescript/renderers/ClassRenderer.ts @@ -43,6 +43,15 @@ ${this.indent(this.renderBlock(content, 2))} content.push(this.renderBlock([getter, setter])); } + if (this.model.patternProperties !== undefined) { + for (const [pattern, patternModel] of Object.entries(this.model.patternProperties)) { + const propertyName = getUniquePropertyName(this.model, `${pattern}${DefaultPropertyNames.patternProperties}`); + const getter = await this.runGetterPreset(propertyName, patternModel, PropertyType.patternProperties); + const setter = await this.runSetterPreset(propertyName, patternModel, PropertyType.patternProperties); + content.push(this.renderBlock([getter, setter])); + } + } + return this.renderBlock(content, 2); } @@ -86,9 +95,9 @@ ${renderer.indent(renderer.renderBlock(assignments))} let signature = ''; if (type === PropertyType.property) { signature = renderer.renderTypeSignature(property, { orUndefined: !isRequired }); - } else if (type === PropertyType.additionalProperty) { - const additionalPropertyType = renderer.renderType(property); - signature = `: Map | undefined`; + } else if (type === PropertyType.additionalProperty || type === PropertyType.patternProperties) { + const mapType = renderer.renderType(property); + signature = `: Map | undefined`; } return `get ${propertyName}()${signature} { return this._${propertyName}; }`; }, @@ -98,9 +107,9 @@ ${renderer.indent(renderer.renderBlock(assignments))} let signature = ''; if (type === PropertyType.property) { signature = renderer.renderTypeSignature(property, { orUndefined: !isRequired }); - } else if (type === PropertyType.additionalProperty) { - const additionalPropertyType = renderer.renderType(property); - signature = `: Map | undefined`; + } else if (type === PropertyType.additionalProperty || type === PropertyType.patternProperties) { + const mapType = renderer.renderType(property); + signature = `: Map | undefined`; } return `set ${propertyName}(${propertyName}${signature}) { this._${propertyName} = ${propertyName}; }`; }, diff --git a/src/helpers/NameHelpers.ts b/src/helpers/NameHelpers.ts index f79d73abc3..15be691778 100644 --- a/src/helpers/NameHelpers.ts +++ b/src/helpers/NameHelpers.ts @@ -4,7 +4,8 @@ import { CommonModel } from 'models'; * Default property names for different aspects of the common model */ export enum DefaultPropertyNames { - additionalProperties = 'additionalProperties' + additionalProperties = 'additionalProperties', + patternProperties = 'PatternProperties' } /** diff --git a/src/models/Preset.ts b/src/models/Preset.ts index 37a32be747..de3257c124 100644 --- a/src/models/Preset.ts +++ b/src/models/Preset.ts @@ -18,7 +18,8 @@ export interface CommonPreset { tuple_type_with_additional_items: { type: 'array', items: [{ type: 'string' }, { type: 'number' }], additionalItems: true }, array_type: { type: 'array', items: { type: 'string' } }, }, + patternProperties: { + '^S(.?*)test&': { + type: 'string' + } + }, required: ['street_name', 'city', 'state', 'house_number', 'array_type'], }; const expected = `export class Address { @@ -33,6 +38,7 @@ describe('TypeScriptGenerator', () => { private _tupleTypeWithAdditionalItems?: [string, number, ...(object | string | number | Array | boolean | null | number)[]]; private _arrayType: Array; private _additionalProperties?: Map | boolean | null | number>; + private _sTestPatternProperties?: Map; constructor(input: { streetName: string, @@ -85,6 +91,9 @@ describe('TypeScriptGenerator', () => { get additionalProperties(): Map | boolean | null | number> | undefined { return this._additionalProperties; } set additionalProperties(additionalProperties: Map | boolean | null | number> | undefined) { this._additionalProperties = additionalProperties; } + + get sTestPatternProperties(): Map | undefined { return this._sTestPatternProperties; } + set sTestPatternProperties(sTestPatternProperties: Map | undefined) { this._sTestPatternProperties = sTestPatternProperties; } }`; const inputModel = await generator.process(doc); @@ -160,6 +169,11 @@ ${content}`; tuple_type_with_additional_items: { type: 'array', items: [{ type: 'string' }, { type: 'number' }], additionalItems: true }, array_type: { type: 'array', items: { type: 'string' } }, }, + patternProperties: { + '^S(.?*)test&': { + type: 'string' + } + }, required: ['street_name', 'city', 'state', 'house_number', 'array_type'], }; const expected = `export interface Address { @@ -173,6 +187,7 @@ ${content}`; tupleTypeWithAdditionalItems?: [string, number, ...(object | string | number | Array | boolean | null | number)[]]; arrayType: Array; additionalProperties?: Map | boolean | null | number>; + sTestPatternProperties?: Map; }`; const interfaceGenerator = new TypeScriptGenerator({modelType: 'interface'});