ts-json-schema-generator
Version:
Generate JSON schema from your Typescript sources
58 lines (48 loc) • 2.2 kB
text/typescript
import ts from "typescript";
import type { Context, NodeParser } from "../NodeParser.js";
import type { SubNodeParser } from "../SubNodeParser.js";
import { AliasType } from "../Type/AliasType.js";
import type { BaseType } from "../Type/BaseType.js";
import { NeverType } from "../Type/NeverType.js";
import type { ReferenceType } from "../Type/ReferenceType.js";
import { getKey } from "../Utils/nodeKey.js";
export class TypeAliasNodeParser implements SubNodeParser {
public constructor(
protected typeChecker: ts.TypeChecker,
protected childNodeParser: NodeParser,
) {}
public supportsNode(node: ts.TypeAliasDeclaration): boolean {
return node.kind === ts.SyntaxKind.TypeAliasDeclaration;
}
public createType(node: ts.TypeAliasDeclaration, context: Context, reference?: ReferenceType): BaseType {
if (node.typeParameters?.length) {
for (const typeParam of node.typeParameters) {
const nameSymbol = this.typeChecker.getSymbolAtLocation(typeParam.name)!;
context.pushParameter(nameSymbol.name);
if (typeParam.default) {
const type = this.childNodeParser.createType(typeParam.default, context);
context.setDefault(nameSymbol.name, type);
}
}
}
const id = this.getTypeId(node, context);
const name = this.getTypeName(node, context);
if (reference) {
reference.setId(id);
reference.setName(name);
}
const type = this.childNodeParser.createType(node.type, context);
if (type instanceof NeverType) {
return new NeverType();
}
return new AliasType(id, type);
}
protected getTypeId(node: ts.TypeAliasDeclaration, context: Context): string {
return `alias-${getKey(node, context)}`;
}
protected getTypeName(node: ts.TypeAliasDeclaration, context: Context): string {
const argumentIds = context.getArguments().map((arg) => arg?.getName());
const fullName = node.name.getText();
return argumentIds.length ? `${fullName}<${argumentIds.join(",")}>` : fullName;
}
}