in jsstub-generator/generate.ts [142:290]
function toTypeName(propertyType: ts.Node | undefined, moduleInfo: ModuleInfo, parentType: string | undefined = undefined, originalDefinition: string | undefined = undefined): TypeInfo {
if (!propertyType) {
return new TypeInfo('undefined', ['undefined']);
}
let result = propertyType.getText();
let arrayDeep = 0;
while (propertyType && propertyType.kind === ts.SyntaxKind.ArrayType) {
arrayDeep++;
propertyType = (<ts.ArrayTypeNode>propertyType).elementType;
}
if (arrayDeep > 0 && propertyType.kind === ts.SyntaxKind.TypeReference) {
let realPropertyType = (<ts.TypeReferenceNode>propertyType).typeName;
return new TypeInfo('new Array()',
[(realPropertyType.kind === ts.SyntaxKind.QualifiedName
? realPropertyType.getText()
: 'text' in realPropertyType
? realPropertyType.text
: realPropertyType) + '[]'.repeat(arrayDeep)], result);
}
if (propertyType.kind === ts.SyntaxKind.AnyKeyword) {
return new TypeInfo('new Object()', ['Object'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.StringKeyword) {
return new TypeInfo('new String()', ['String'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.NumberKeyword) {
return new TypeInfo('new Number()', ['Number'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.UnknownKeyword) {
return new TypeInfo('undefined', ['Object'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.BooleanKeyword) {
return new TypeInfo('new Boolean()', ['Boolean'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.VoidKeyword) {
return new TypeInfo('undefined', ['undefined'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.ObjectKeyword) {
return new TypeInfo('new Object()', ['Object'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.UndefinedKeyword) {
return new TypeInfo('undefined', ['undefined'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.LiteralType) {
return new TypeInfo(result, [result], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.BigIntKeyword) {
return new TypeInfo('BigInt(0)', ['BigInt'], originalDefinition);
} else if (parentType && propertyType.kind === ts.SyntaxKind.ThisType) {
return new TypeInfo('new ' + parentType + '()', [parentType], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.SymbolKeyword) {
return new TypeInfo('new Symbol()', ['Symbol'], originalDefinition);
} else if (result === 'unique symbol') {
return new TypeInfo('new Symbol()', ['Symbol'], originalDefinition);
} else if (propertyType.kind === ts.SyntaxKind.FunctionType) {
return new TypeInfo('new Function()', ['Function'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.ConstructorType) {
return new TypeInfo('new Function()', ['Function'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.TupleType) {
return new TypeInfo('new Object()', ['Object'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.TypeLiteral) {
// XXXX
return new TypeInfo('new Object()', ['Object'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.FirstTypeNode) {
return new TypeInfo('new Boolean()', ['Boolean'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.TypeQuery) {
const entityName = (propertyType as ts.TypeQueryNode).exprName;
let typeName = 'undefined';
if(entityName.kind == ts.SyntaxKind.Identifier) {
typeName = (entityName as ts.Identifier).text;
} else if (entityName.kind == ts.SyntaxKind.QualifiedName) {
typeName = (entityName as ts.QualifiedName).getText();
}
return new TypeInfo('new ' + typeName + '()', [typeName], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.TypeOperator) {
return toTypeName((propertyType as ts.TypeOperatorNode).type, moduleInfo, parentType, originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.TypeReference) {
let realPropertyType = (<ts.TypeReferenceNode>propertyType).typeName;
if (moduleInfo.aliases.has(realPropertyType.getText())) {
return toTypeName(
moduleInfo.aliases.get(realPropertyType.getText())!,
moduleInfo,
parentType,
originalDefinition ? originalDefinition : realPropertyType.getText()
);
} else {
const type = checker.getTypeAtLocation(propertyType);
const symbol = type.symbol || type.aliasSymbol;
let jsType = 'new Object()';
let jsdocType = 'Object';
if (symbol) {
const decls = symbol.getDeclarations() as ts.Declaration[];
let referencesInterface: boolean = false;
decls.forEach(d => {
if (d.kind == ts.SyntaxKind.InterfaceDeclaration) {
referencesInterface = true;
}
});
if (referencesInterface) {
jsType = 'new ' + realPropertyType.getText() + '()';
jsdocType = realPropertyType.getText();
if ((!moduleInfo.classes.has(jsdocType)) && (moduleInfo.aliases.has(jsdocType))) {
return toTypeName(
moduleInfo.aliases.get(jsdocType)!,
moduleInfo,
parentType,
originalDefinition ? originalDefinition : realPropertyType.getText()
);
}
}
} else if (type.flags == ts.TypeFlags.Number) {
jsType = 'new Number()';
jsdocType = 'Number';
}
return new TypeInfo(jsType, [jsdocType], originalDefinition ? originalDefinition : realPropertyType.getText());
}
} else if (propertyType.kind === ts.SyntaxKind.IndexedAccessType && result === 'ArrayBufferTypes[keyof ArrayBufferTypes]') {
return new TypeInfo('new ArrayBuffer()', ['ArrayBuffer'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind === ts.SyntaxKind.UnionType) {
const types = (<ts.TypeNode[]> ((propertyType as any).types))
.filter(t => t.kind !== ts.SyntaxKind.UndefinedKeyword && !(t.kind === ts.SyntaxKind.LiteralType && t.getText() === 'null') && t.kind !== ts.SyntaxKind.TypeQuery);
let reducedTypeInfo: TypeInfo | undefined = undefined;
if (types.length == 1) {
reducedTypeInfo = toTypeName(types[0], moduleInfo, parentType, originalDefinition ? originalDefinition : result);
}
let jsdocType = (<ts.TypeNode[]> ((propertyType as any).types))
.map(typeNode => toTypeName(typeNode, moduleInfo, parentType, originalDefinition ? originalDefinition : result))
.map(ti => ti.jsdocType)
.flat();
if(reducedTypeInfo) {
return new TypeInfo(reducedTypeInfo.jsType, jsdocType, originalDefinition ? originalDefinition : result);
} else {
return new TypeInfo('new Object()', jsdocType, originalDefinition ? originalDefinition : result);
}
} else if (propertyType.kind === ts.SyntaxKind.IntersectionType) {
const types = (<ts.TypeNode[]> ((propertyType as any).types))
.filter(t => t.kind !== ts.SyntaxKind.UndefinedKeyword && !(t.kind === ts.SyntaxKind.LiteralType && t.getText() === 'null') && t.kind !== ts.SyntaxKind.TypeQuery);
if (types.length == 1) {
return toTypeName(types[0], moduleInfo, parentType, originalDefinition ? originalDefinition : result);
}
return new TypeInfo('new Object()', ['Object'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind == ts.SyntaxKind.ParenthesizedType) {
return toTypeName((propertyType as ts.ParenthesizedTypeNode).type, moduleInfo, parentType, originalDefinition ? originalDefinition : result);
} else if (propertyType.kind == ts.SyntaxKind.ConditionalType && parentType === 'SubtleCrypto') {
return toTypeName(moduleInfo.aliases.get('KeyFormat'), moduleInfo, parentType, originalDefinition ? originalDefinition : result);
} else if (propertyType.kind == ts.SyntaxKind.MappedType && (parentType === 'ResponseInit' || parentType === 'RequestInit' || parentType === 'PushSubscriptionJSON')) {
return new TypeInfo('{}', ['Object.<String,String>'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind == ts.SyntaxKind.MappedType && (parentType === 'AudioWorkletNodeOptions')) {
return new TypeInfo('{}', ['Object.<String,Number>'], originalDefinition ? originalDefinition : result);
} else if (propertyType.kind == ts.SyntaxKind.MappedType && (parentType === 'Object')) {
return new TypeInfo('new Object()', ['Object'], originalDefinition ? originalDefinition : result);
} else {
console.log('Unhandled type code: ' + ts.SyntaxKind[propertyType.kind] + ' / ' + result + ' / ' + parentType);
return new TypeInfo('undefined', ['Object'], originalDefinition ? originalDefinition : result);
}
}