diff --git a/packages/quicktype-typescript-input/src/index.ts b/packages/quicktype-typescript-input/src/index.ts index e29f49118f..f94edb4007 100644 --- a/packages/quicktype-typescript-input/src/index.ts +++ b/packages/quicktype-typescript-input/src/index.ts @@ -125,6 +125,30 @@ function patchGeneratorForBuiltinTypes( }; } +// typescript-json-schema copies JSDoc `@type {string}` annotations into the +// generated schema verbatim. Strip the JSDoc braces so the value is a valid +// JSON Schema type. +function sanitizeTypeAnnotations(value: unknown): void { + if (Array.isArray(value)) { + value.forEach(sanitizeTypeAnnotations); + return; + } + + if (value === null || typeof value !== "object") { + return; + } + + const schema = value as Record; + if (typeof schema.type === "string") { + const match = /^\{([^{}]+)\}$/.exec(schema.type); + if (match !== null) { + schema.type = match[1]; + } + } + + Object.values(schema).forEach(sanitizeTypeAnnotations); +} + // FIXME: We're stringifying and then parsing this schema again. Just pass around // the schema directly. export function schemaForTypeScriptSources( @@ -151,6 +175,8 @@ export function schemaForTypeScriptSources( patchGeneratorForBuiltinTypes(generator, program); const schema = generateSchema(program, "*", settings, undefined, generator); + sanitizeTypeAnnotations(schema); + const uris: string[] = []; let topLevelName = ""; diff --git a/test/unit/typescript-input.test.ts b/test/unit/typescript-input.test.ts index 2e5f6a8842..dedb3335d2 100644 --- a/test/unit/typescript-input.test.ts +++ b/test/unit/typescript-input.test.ts @@ -84,6 +84,23 @@ describe("schemaForTypeScriptSources", () => { expect(schema.definitions.Person.type).toBe("object"); }); + // https://github.com/glideapps/quicktype/issues/2695 + test("strips braces from JSDoc type annotations", () => { + const { schema } = schemaForSource(` + export type Person = { + /** + * @type {string} + * @memberOf {Person} + */ + name: string; + }; + + export type MemberInfo = Required; + `); + + expect(schema.definitions.Person.properties.name.type).toBe("string"); + }); + test("class property initializers become defaults", () => { const { schema } = schemaForSource(` export class Config {