Skip to content

Commit 8be3ade

Browse files
committed
Add type for definitons to get rid of a bunch of anys
1 parent c0d57b1 commit 8be3ade

File tree

1 file changed

+53
-22
lines changed

1 file changed

+53
-22
lines changed

typescript-json-schema.ts

+53-22
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,30 @@ export function getDefaultArgs() {
2121
};
2222
}
2323

24+
export type Definition = {
25+
$ref?: string,
26+
description?: string,
27+
allOf?: Definition[],
28+
oneOf?: Definition[],
29+
anyOf?: Definition[],
30+
title?: string,
31+
type?: string | string[],
32+
definitions?: {[key: string]: any},
33+
format?: string,
34+
items?: Definition,
35+
minItems?: number,
36+
additionalItems?: {
37+
anyOf: Definition
38+
},
39+
enum?: string[] | Definition[],
40+
default?: string | number | boolean | Object,
41+
additionalProperties?: Definition,
42+
required?: string[],
43+
propertyOrder?: string[],
44+
properties?: {},
45+
defaultProperties?: string[],
46+
};
47+
2448
export class JsonSchemaGenerator {
2549
/**
2650
* JSDoc keywords that should be used to annotate the JSON schema.
@@ -50,15 +74,15 @@ export class JsonSchemaGenerator {
5074
private inheritingTypes: { [baseName: string]: string[] };
5175
private tc: ts.TypeChecker;
5276

53-
private reffedDefinitions: { [key: string]: any } = {};
77+
private reffedDefinitions: { [key: string]: Definition } = {};
5478

5579
constructor(allSymbols: { [name: string]: ts.Type }, inheritingTypes: { [baseName: string]: string[] }, tc: ts.TypeChecker, private args = getDefaultArgs()) {
5680
this.allSymbols = allSymbols;
5781
this.inheritingTypes = inheritingTypes;
5882
this.tc = tc;
5983
}
6084

61-
public get ReffedDefinitions(): { [key: string]: any } {
85+
public get ReffedDefinitions(): { [key: string]: Definition } {
6286
return this.reffedDefinitions;
6387
}
6488

@@ -76,7 +100,10 @@ export class JsonSchemaGenerator {
76100
return isNaN(num) ? value : num;
77101
}
78102

79-
private parseCommentsIntoDefinition(symbol: ts.Symbol, definition: {description: string}, otherAnnotations: {}): void {
103+
/**
104+
* Parse the comments of a symbol into the definition and other annotations.
105+
*/
106+
private parseCommentsIntoDefinition(symbol: ts.Symbol, definition: {description?: string}, otherAnnotations: {}): void {
80107
if (!symbol) {
81108
return;
82109
}
@@ -128,7 +155,7 @@ export class JsonSchemaGenerator {
128155
return propertyType as any;
129156
}
130157

131-
private getDefinitionForRootType(propertyType: ts.Type, tc: ts.TypeChecker, reffedType: ts.Symbol, definition: any) {
158+
private getDefinitionForRootType(propertyType: ts.Type, tc: ts.TypeChecker, reffedType: ts.Symbol, definition: Definition) {
132159
const symbol = propertyType.getSymbol();
133160

134161
const tupleType = this.resolveTupleType(propertyType);
@@ -210,7 +237,7 @@ export class JsonSchemaGenerator {
210237

211238
const reffedType = this.getReferencedTypeSymbol(prop, tc);
212239

213-
let definition: any = this.getTypeDefinition(propertyType, tc, undefined, undefined, prop, reffedType);
240+
let definition = this.getTypeDefinition(propertyType, tc, undefined, undefined, prop, reffedType);
214241
if (this.args.useTitle) {
215242
definition.title = propertyName;
216243
}
@@ -233,7 +260,7 @@ export class JsonSchemaGenerator {
233260
vm.runInNewContext("sandboxvar=" + initial.getText(), sandbox);
234261

235262
initial = sandbox.sandboxvar;
236-
if (initial === null || typeof (initial) === "string" || typeof (initial) === "number" || typeof (initial) === "boolean" || Object.prototype.toString.call(initial) === "[object Array]") {
263+
if (initial === null || typeof initial === "string" || typeof initial === "number" || typeof initial === "boolean" || Object.prototype.toString.call(initial) === "[object Array]") {
237264
definition.default = initial;
238265
} else if (initial) {
239266
console.warn("unknown initializer for property " + propertyName + ": " + initial);
@@ -247,12 +274,12 @@ export class JsonSchemaGenerator {
247274
return definition;
248275
}
249276

250-
private getEnumDefinition(clazzType: ts.Type, tc: ts.TypeChecker, definition: any): any {
277+
private getEnumDefinition(clazzType: ts.Type, tc: ts.TypeChecker, definition: Definition): Definition {
251278
const node = clazzType.getSymbol().getDeclarations()[0];
252279
const fullName = tc.typeToString(clazzType, undefined, ts.TypeFormatFlags.UseFullyQualifiedType);
253280
const enm = <ts.EnumDeclaration>node;
254281

255-
var enumValues: any[] = [];
282+
var enumValues: Definition[] = [];
256283
let enumTypes: string[] = [];
257284

258285
const addType = (type: string) => {
@@ -301,16 +328,16 @@ export class JsonSchemaGenerator {
301328
}
302329

303330
if (enumValues.length > 0) {
304-
definition["enum"] = enumValues.sort();
331+
definition.enum = enumValues.sort();
305332
}
306333

307334
return definition;
308335
}
309336

310-
private getUnionDefinition(unionType: ts.UnionType, prop: ts.Symbol, tc: ts.TypeChecker, unionModifier: string, definition: any): any {
337+
private getUnionDefinition(unionType: ts.UnionType, prop: ts.Symbol, tc: ts.TypeChecker, unionModifier: string, definition: Definition) {
311338
const enumValues: (string | number | boolean)[] = [];
312339
const simpleTypes: string[] = [];
313-
const schemas: any[] = [];
340+
const schemas: Definition[] = [];
314341

315342
const addSimpleType = (type: string) => {
316343
if (simpleTypes.indexOf(type) === -1) {
@@ -338,7 +365,11 @@ export class JsonSchemaGenerator {
338365
} else {
339366
const keys = Object.keys(def);
340367
if (keys.length === 1 && keys[0] === "type") {
341-
addSimpleType(def.type);
368+
if (typeof def.type !== "string") {
369+
console.error("Expected only a simple type.");
370+
} else {
371+
addSimpleType(def.type);
372+
}
342373
} else {
343374
schemas.push(def);
344375
}
@@ -356,7 +387,7 @@ export class JsonSchemaGenerator {
356387
if (isOnlyBooleans) {
357388
addSimpleType("boolean");
358389
} else {
359-
const enumSchema: any = { enum: enumValues.sort() };
390+
const enumSchema: Definition = { enum: enumValues.sort() };
360391

361392
// If all values are of the same primitive type, add a "type" field to the schema
362393
if (enumValues.every((x) => { return typeof x === "string"; })) {
@@ -387,7 +418,7 @@ export class JsonSchemaGenerator {
387418
return definition;
388419
}
389420

390-
private getClassDefinition(clazzType: ts.Type, tc: ts.TypeChecker, definition: any): any {
421+
private getClassDefinition(clazzType: ts.Type, tc: ts.TypeChecker, definition: Definition): Definition {
391422
const node = clazzType.getSymbol().getDeclarations()[0];
392423
const clazz = <ts.ClassDeclaration>node;
393424
const props = tc.getPropertiesOfType(clazzType);
@@ -476,7 +507,7 @@ export class JsonSchemaGenerator {
476507
description: true
477508
};
478509

479-
private addSimpleType(def: any, type: string) {
510+
private addSimpleType(def: Definition, type: string) {
480511
for (let k in def) {
481512
if (!this.simpleTypesAllowedProperties[k]) {
482513
return false;
@@ -485,7 +516,7 @@ export class JsonSchemaGenerator {
485516

486517
if (!def.type) {
487518
def.type = type;
488-
} else if (def.type.push) {
519+
} else if (typeof def.type !== "string") {
489520
if (!(<Object[]>def.type).every((val) => { return typeof val === "string"; })) {
490521
return false;
491522
}
@@ -505,7 +536,7 @@ export class JsonSchemaGenerator {
505536
return true;
506537
}
507538

508-
private makeNullable(def: any) {
539+
private makeNullable(def: Definition) {
509540
if (!this.addSimpleType(def, "null")) {
510541
let union = def.oneOf || def.anyOf;
511542
if (union) {
@@ -524,8 +555,8 @@ export class JsonSchemaGenerator {
524555
return def;
525556
}
526557

527-
private getTypeDefinition(typ: ts.Type, tc: ts.TypeChecker, asRef = this.args.useRef, unionModifier: string = "anyOf", prop?: ts.Symbol, reffedType?: ts.Symbol): any {
528-
const definition: any = {}; // real definition
558+
private getTypeDefinition(typ: ts.Type, tc: ts.TypeChecker, asRef = this.args.useRef, unionModifier: string = "anyOf", prop?: ts.Symbol, reffedType?: ts.Symbol): Definition {
559+
const definition: Definition = {}; // real definition
529560
let returnedDefinition = definition; // returned definition, may be a $ref
530561

531562
const symbol = typ.getSymbol();
@@ -605,7 +636,7 @@ export class JsonSchemaGenerator {
605636
return returnedDefinition;
606637
}
607638

608-
public getSchemaForSymbol(symbolName: string, includeReffedDefinitions: boolean = true): any {
639+
public getSchemaForSymbol(symbolName: string, includeReffedDefinitions: boolean = true): Definition {
609640
if(!this.allSymbols[symbolName]) {
610641
throw `type ${symbolName} not found`;
611642
}
@@ -619,7 +650,7 @@ export class JsonSchemaGenerator {
619650
return def;
620651
}
621652

622-
public getSchemaForSymbols(symbols: { [name: string]: ts.Type }): any {
653+
public getSchemaForSymbols(symbols: { [name: string]: ts.Type }): Definition {
623654
const root = {
624655
"$schema": "http://json-schema.org/draft-04/schema#",
625656
definitions: {}
@@ -698,7 +729,7 @@ export function generateSchema(program: ts.Program, fullTypeName: string, args =
698729
});
699730

700731
const generator = new JsonSchemaGenerator(allSymbols, inheritingTypes, typeChecker, args);
701-
let definition: any;
732+
let definition: Definition;
702733
if (fullTypeName === "*") { // All types in file(s)
703734
definition = generator.getSchemaForSymbols(userSymbols);
704735
} else { // Use specific type as root object

0 commit comments

Comments
 (0)