diff --git a/test/programs/typeof-keyword-methods/main.ts b/test/programs/typeof-keyword-methods/main.ts new file mode 100644 index 00000000..8c82137a --- /dev/null +++ b/test/programs/typeof-keyword-methods/main.ts @@ -0,0 +1,4 @@ +interface MyObject { + foo: () => string; + bar(): string; +} diff --git a/test/programs/typeof-keyword-methods/schema.json b/test/programs/typeof-keyword-methods/schema.json new file mode 100644 index 00000000..869a6b1c --- /dev/null +++ b/test/programs/typeof-keyword-methods/schema.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "foo": { + "typeof": "function" + }, + "bar": { + "typeof": "function" + } + }, + "required": [ + "bar", + "foo" + ], + "type": "object" +} + diff --git a/test/schema.test.ts b/test/schema.test.ts index e503b246..c1cca312 100644 --- a/test/schema.test.ts +++ b/test/schema.test.ts @@ -19,7 +19,6 @@ export function assertSchema(group: string, type: string, settings: TJS.PartialA const files = [resolve(BASE + group + "/main.ts")]; const actual = TJS.generateSchema(TJS.getProgramFromFiles(files, compilerOptions), type, settings, files); - // writeFileSync(BASE + group + "/schema.json", stringify(actual, {space: 4}) + "\n\n"); const file = readFileSync(BASE + group + "/schema.json", "utf8"); @@ -190,6 +189,7 @@ describe("schema", () => { assertSchema("annotation-id", "MyObject"); assertSchema("typeof-keyword", "MyObject", {typeOfKeyword: true}); + assertSchema("typeof-keyword-methods", "MyObject", {typeOfKeyword: true}); assertSchema("user-validation-keywords", "MyObject", { validationKeywords: [ "chance", "important" ] diff --git a/typescript-json-schema.ts b/typescript-json-schema.ts index c287eb39..ea7e1ce7 100644 --- a/typescript-json-schema.ts +++ b/typescript-json-schema.ts @@ -450,9 +450,10 @@ export class JsonSchemaGenerator { } private getDefinitionForProperty(prop: ts.Symbol, node: ts.Node) { - if (prop.flags & ts.SymbolFlags.Method) { + if ((prop.flags & ts.SymbolFlags.Method) && !this.args.typeOfKeyword) { return null; } + const propertyName = prop.getName(); const propertyType = this.tc.getTypeOfSymbolAtLocation(prop, node); @@ -785,7 +786,7 @@ export class JsonSchemaGenerator { const requiredProps = props.reduce((required: string[], prop: ts.Symbol) => { const def = {}; this.parseCommentsIntoDefinition(prop, def, {}); - if (!(prop.flags & ts.SymbolFlags.Optional) && !(prop.flags & ts.SymbolFlags.Method) && !(prop).mayBeUndefined && !def.hasOwnProperty("ignore")) { + if (!(prop.flags & ts.SymbolFlags.Optional) && (this.args.typeOfKeyword || !(prop.flags & ts.SymbolFlags.Method)) && !(prop).mayBeUndefined && !def.hasOwnProperty("ignore")) { required.push(prop.getName()); } return required; @@ -833,7 +834,7 @@ export class JsonSchemaGenerator { reffedType = undefined; } - if (this.args.typeOfKeyword && (typ.flags & ts.TypeFlags.Object) && ((typ).objectFlags & ts.ObjectFlags.Anonymous)) { + if (this.args.typeOfKeyword && ((typ.flags & ts.TypeFlags.Object) || typ.symbol.flags & ts.SymbolFlags.Method) && ((typ).objectFlags & ts.ObjectFlags.Anonymous)) { definition.typeof = "function"; return definition; }