diff --git a/src/NodeParser/InterfaceAndClassNodeParser.ts b/src/NodeParser/InterfaceAndClassNodeParser.ts index 4b0287231..07114e841 100644 --- a/src/NodeParser/InterfaceAndClassNodeParser.ts +++ b/src/NodeParser/InterfaceAndClassNodeParser.ts @@ -119,12 +119,27 @@ export class InterfaceAndClassNodeParser implements SubNodeParser { } return members; }, [] as (ts.PropertyDeclaration | ts.PropertySignature | ts.ParameterPropertyDeclaration)[]) - .filter((member) => isPublic(member) && !isStatic(member) && member.type && !isNodeHidden(member)) + .filter((member) => isPublic(member) && !isStatic(member) && !isNodeHidden(member)) + .reduce((entries, member) => { + let memberType: ts.Node | undefined = member.type; + + // Use the type checker if the member has no explicit type + // Ignore members without an initializer. They have no useful type. + if (memberType === undefined && member.initializer !== undefined) { + const type = this.typeChecker.getTypeAtLocation(member); + memberType = this.typeChecker.typeToTypeNode(type, node, ts.NodeBuilderFlags.NoTruncation); + } + + if (memberType !== undefined) { + return [...entries, { member, memberType }]; + } + return entries; + }, []) .map( - (member) => + ({ member, memberType }) => new ObjectProperty( this.getPropertyName(member.name), - this.childNodeParser.createType(member.type!, context), + this.childNodeParser.createType(memberType, context), !member.questionToken ) ) diff --git a/test/valid-data/class-single/main.ts b/test/valid-data/class-single/main.ts index 9a43e8d85..628e13d7f 100644 --- a/test/valid-data/class-single/main.ts +++ b/test/valid-data/class-single/main.ts @@ -3,7 +3,8 @@ export class MyObject { public static staticProp: number; public propA: number; - public propB: number; + // Test that types can be inferred + public propB = 42; // Properties without type must be ignored public noType; @@ -17,8 +18,14 @@ export class MyObject { readonly readonlyProp: string; // Constructors must be ignored - public constructor(protected a: number, private b: number, c: number, public propC: number, - public propD?: string) { + public constructor( + protected a: number, + private b: number, + c: number, + // Test that types can be inferred + public propC = 42, + public propD?: string + ) { this.privateProp = false; }