diff --git a/typescript-json-schema.ts b/typescript-json-schema.ts index d1e8f561..522d489c 100644 --- a/typescript-json-schema.ts +++ b/typescript-json-schema.ts @@ -121,6 +121,7 @@ export interface Definition extends Omit { propertyOrder?: string[]; defaultProperties?: string[]; typeof?: "function"; + parameters?: Definition[]; // Fields that must be redefined because they make use of this definition itself items?: DefinitionOrBoolean | DefinitionOrBoolean[]; @@ -552,16 +553,16 @@ export class JsonSchemaGenerator { if (comments.length) { definition.description = comments .map((comment) => { - const newlineNormalizedComment = comment.text.replace(/\r\n/g, "\n"); + const newlineNormalizedComment = comment.text.replace(/\r\n/g, "\n"); - // If a comment contains a "{@link XYZ}" inline tag that could not be - // resolved by the TS checker, then this comment will contain a trailing - // whitespace that we need to remove. - if (comment.kind === "linkText") { - return newlineNormalizedComment.trim(); - } + // If a comment contains a "{@link XYZ}" inline tag that could not be + // resolved by the TS checker, then this comment will contain a trailing + // whitespace that we need to remove. + if (comment.kind === "linkText") { + return newlineNormalizedComment.trim(); + } - return newlineNormalizedComment; + return newlineNormalizedComment; }) .join("").trim(); } @@ -1002,6 +1003,18 @@ export class JsonSchemaGenerator { return definition; } + private getFunctionDefinition(funcType: ts.Type, definition: Definition): Definition { + const node = funcType.getSymbol()!.getDeclarations()![0]; + + const parameters = (node as ts.FunctionLikeDeclaration).parameters; + definition.typeof = "function"; + definition.parameters = parameters + .map((p) => this.tc.getTypeAtLocation(p.type!)) + .map((type) => this.getTypeDefinition(type)); + + return definition; + } + private getClassDefinition(clazzType: ts.Type, definition: Definition): Definition { const node = clazzType.getSymbol()!.getDeclarations()![0]; @@ -1011,11 +1024,6 @@ export class JsonSchemaGenerator { return definition; } - if (this.args.typeOfKeyword && node.kind === ts.SyntaxKind.FunctionType) { - definition.typeof = "function"; - return definition; - } - const clazz = node; const props = this.tc.getPropertiesOfType(clazzType).filter((prop) => { // filter never @@ -1195,15 +1203,6 @@ export class JsonSchemaGenerator { reffedType = undefined; } - if ( - this.args.typeOfKeyword && - typ.flags & ts.TypeFlags.Object && - (typ).objectFlags & ts.ObjectFlags.Anonymous - ) { - definition.typeof = "function"; - return definition; - } - let returnedDefinition = definition; // returned definition, may be a $ref // Parse property comments now to skip recursive if ignore. @@ -1374,6 +1373,8 @@ export class JsonSchemaGenerator { // {} is TypeLiteral with no members. Need special case because it doesn't have declarations. definition.type = "object"; definition.properties = {}; + } else if (this.args.typeOfKeyword && node && ts.isFunctionLike(node)) { + this.getFunctionDefinition(typ, definition); } else { this.getClassDefinition(typ, definition); }