Skip to content

Commit

Permalink
fix: fixing circular dependencies
Browse files Browse the repository at this point in the history
style: fixed typos
  • Loading branch information
filipomar authored and Filipe Pomar committed May 26, 2022
1 parent 42ce3b6 commit 6119cbe
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 8 deletions.
2 changes: 1 addition & 1 deletion factory/parser.ts
Expand Up @@ -122,7 +122,7 @@ export function createParser(program: ts.Program, config: Config, augmentor?: Pa
.addNodeParser(new TypeReferenceNodeParser(typeChecker, chainNodeParser))
.addNodeParser(new ExpressionWithTypeArgumentsNodeParser(typeChecker, chainNodeParser))

.addNodeParser(new IndexedAccessTypeNodeParser(chainNodeParser))
.addNodeParser(new IndexedAccessTypeNodeParser(typeChecker, chainNodeParser))
.addNodeParser(new TypeofNodeParser(typeChecker, chainNodeParser))
.addNodeParser(new MappedTypeNodeParser(chainNodeParser, mergedConfig.additionalProperties))
.addNodeParser(new ConditionalTypeNodeParser(typeChecker, chainNodeParser))
Expand Down
39 changes: 35 additions & 4 deletions src/NodeParser/IndexedAccessTypeNodeParser.ts
Expand Up @@ -12,17 +12,48 @@ import { derefType } from "../Utils/derefType";
import { getTypeByKey } from "../Utils/typeKeys";

export class IndexedAccessTypeNodeParser implements SubNodeParser {
public constructor(protected childNodeParser: NodeParser) {}
public constructor(protected typeChecker: ts.TypeChecker, protected childNodeParser: NodeParser) {}

public supportsNode(node: ts.IndexedAccessTypeNode): boolean {
public supportsNode(node: ts.TypeNode): boolean {
return node.kind === ts.SyntaxKind.IndexedAccessType;
}

private createIndexedType(objectType: ts.TypeNode, context: Context, indexType: BaseType) {
if (ts.isTypeReferenceNode(objectType) && indexType instanceof LiteralType) {
const declaration = this.typeChecker.getSymbolAtLocation(objectType.typeName)?.declarations?.[0];

if (!declaration || !ts.isTypeAliasDeclaration(declaration) || !ts.isTypeLiteralNode(declaration.type)) {
return undefined;
}

const member = declaration.type.members.find(
(m): m is ts.PropertySignature & { type: ts.TypeNode } =>
ts.isPropertySignature(m) &&
Boolean(m.type) &&
ts.isIdentifier(m.name) &&
m.name.text === indexType.getValue()
);

return member && this.childNodeParser.createType(member.type, context);
}

return undefined;
}

public createType(node: ts.IndexedAccessTypeNode, context: Context): BaseType | undefined {
const objectType = derefType(this.childNodeParser.createType(node.objectType, context));
const indexType = derefType(this.childNodeParser.createType(node.indexType, context));
if (indexType === undefined) {
return undefined;
}

if (objectType === undefined || indexType === undefined) {
const indexedType = this.createIndexedType(node.objectType, context, indexType);
if (indexedType) {
// indexed type was successfully retrieved
return indexedType;
}

const objectType = derefType(this.childNodeParser.createType(node.objectType, context));
if (objectType === undefined) {
return undefined;
}

Expand Down
6 changes: 3 additions & 3 deletions src/NodeParser/TypeReferenceNodeParser.ts
Expand Up @@ -6,7 +6,7 @@ import { ArrayType } from "../Type/ArrayType";
import { BaseType } from "../Type/BaseType";
import { StringType } from "../Type/StringType";

const invlidTypes: { [index: number]: boolean } = {
const invalidTypes: { [index: number]: boolean } = {
[ts.SyntaxKind.ModuleDeclaration]: true,
[ts.SyntaxKind.VariableDeclaration]: true,
};
Expand All @@ -23,7 +23,7 @@ export class TypeReferenceNodeParser implements SubNodeParser {
if (typeSymbol.flags & ts.SymbolFlags.Alias) {
const aliasedSymbol = this.typeChecker.getAliasedSymbol(typeSymbol);
return this.childNodeParser.createType(
aliasedSymbol.declarations!.filter((n: ts.Declaration) => !invlidTypes[n.kind])[0],
aliasedSymbol.declarations!.filter((n: ts.Declaration) => !invalidTypes[n.kind])[0],
this.createSubContext(node, context)
);
} else if (typeSymbol.flags & ts.SymbolFlags.TypeParameter) {
Expand All @@ -40,7 +40,7 @@ export class TypeReferenceNodeParser implements SubNodeParser {
return new AnnotatedType(new StringType(), { format: "regex" }, false);
} else {
return this.childNodeParser.createType(
typeSymbol.declarations!.filter((n: ts.Declaration) => !invlidTypes[n.kind])[0],
typeSymbol.declarations!.filter((n: ts.Declaration) => !invalidTypes[n.kind])[0],
this.createSubContext(node, context)
);
}
Expand Down
1 change: 1 addition & 0 deletions test/valid-data-type.test.ts
Expand Up @@ -73,6 +73,7 @@ describe("valid-data-type", () => {
it("type-indexed-access-object-1", assertValidSchema("type-indexed-access-object-1", "MyType"));
it("type-indexed-access-object-2", assertValidSchema("type-indexed-access-object-2", "MyType"));
it("type-indexed-access-keyof", assertValidSchema("type-indexed-access-keyof", "MyType"));
it("type-indexed-circular-access", assertValidSchema("type-indexed-circular-access", "*"));
it("type-keyof-tuple", assertValidSchema("type-keyof-tuple", "MyType"));
it("type-keyof-object", assertValidSchema("type-keyof-object", "MyType"));
it("type-keyof-object-function", assertValidSchema("type-keyof-object-function", "MyType"));
Expand Down
12 changes: 12 additions & 0 deletions test/valid-data/type-indexed-circular-access/main.ts
@@ -0,0 +1,12 @@
type Alpha = { stringProp: string; betaStringProp: Beta['stringProp']; }
type TypedAlphaWithDefault<T = number> = { tProp: T; betaStringProp: Beta['stringProp']; }
type TypedAlphaWithoutDefault<T, E> = { tProp: T; eProp: E; betaStringProp: Beta['stringProp']; }

export type Beta = {
stringProp: string;
alphaStringProp: Alpha['stringProp'];
alphaNumberDefaultProp: TypedAlphaWithDefault["tProp"]
alphaNumberWithoutDefaultProp: TypedAlphaWithoutDefault<number, string>["tProp"]
alphaUnionProp: TypedAlphaWithoutDefault<number | null, string>["tProp" | "eProp"]
alphaKeyofProp: TypedAlphaWithoutDefault<number | null, string>[keyof TypedAlphaWithoutDefault<number | null, string>]
}
46 changes: 46 additions & 0 deletions test/valid-data/type-indexed-circular-access/schema.json
@@ -0,0 +1,46 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Beta",
"definitions": {
"Beta": {
"type": "object",
"properties": {
"alphaNumberDefaultProp": {
"type": "number"
},
"alphaNumberWithoutDefaultProp": {
"type": "number"
},
"stringProp": {
"type": "string"
},
"alphaStringProp": {
"type": "string"
},
"alphaUnionProp": {
"type": [
"number",
"null",
"string"
]
},
"alphaKeyofProp": {
"type": [
"number",
"null",
"string"
]
}
},
"required": [
"stringProp",
"alphaStringProp",
"alphaNumberDefaultProp",
"alphaNumberWithoutDefaultProp",
"alphaUnionProp",
"alphaKeyofProp"
],
"additionalProperties": false
}
}
}

0 comments on commit 6119cbe

Please sign in to comment.