UNPKG

flowgen

Version:

Generate flowtype definition files from TypeScript

730 lines (570 loc) 29.5 kB
"use strict"; exports.__esModule = true; exports.default = void 0; exports.fixDefaultTypeArguments = fixDefaultTypeArguments; exports.getFullyQualifiedName = getFullyQualifiedName; exports.getFullyQualifiedPropertyAccessExpression = getFullyQualifiedPropertyAccessExpression; exports.getLeftMostPropertyAccessExpression = getLeftMostPropertyAccessExpression; exports.getTypeofFullyQualifiedName = getTypeofFullyQualifiedName; exports.printEntityName = printEntityName; exports.printFlowGenHelper = printFlowGenHelper; exports.printPropertyAccessExpression = printPropertyAccessExpression; exports.printType = void 0; var ts = _interopRequireWildcard(require("typescript")); var _util = _interopRequireDefault(require("util")); var printers = _interopRequireWildcard(require("./index")); var _checker = require("../checker"); var logger = _interopRequireWildcard(require("../logger")); var _env = require("../env"); var _smartIdentifiers = require("./smart-identifiers"); var _errorMessage = require("../errors/error-message"); var _options = require("../options"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function printEntityName(type) { if (type.kind === ts.SyntaxKind.QualifiedName) { return printers.relationships.namespace(type.left.kind === ts.SyntaxKind.Identifier ? type.left.text : printEntityName(type.left)) + printEntityName(type.right); } else if (type.kind === ts.SyntaxKind.Identifier) { return printers.relationships.namespace(type.text, true); } else { return ""; } } function printPropertyAccessExpression(type) { if (type.kind === ts.SyntaxKind.PropertyAccessExpression) { return printers.relationships.namespace(ts.isIdentifier(type.expression) ? type.expression.text : // @ts-expect-error todo(flow->ts) printPropertyAccessExpression(type.expression)) + printPropertyAccessExpression(type.name); } else if (type.kind === ts.SyntaxKind.Identifier) { return printers.relationships.namespace( // @ts-expect-error todo(flow->ts) printers.identifiers.print(type.text), true); } else { return ""; } } function getLeftMostPropertyAccessExpression(type) { if (type.kind === ts.SyntaxKind.PropertyAccessExpression) { return ts.isIdentifier(type.expression) ? type.expression : // @ts-expect-error todo(flow->ts) getLeftMostPropertyAccessExpression(type.expression); } else if (type.kind === ts.SyntaxKind.Identifier) { return type; } } function getFullyQualifiedPropertyAccessExpression(symbol, type, delimiter = "$") { if (_checker.checker.current) { var _symbol$parent, _symbol$parent$valueD, _symbol$parent2, _symbol$parent2$value, _symbol$parent3; const typeChecker = _checker.checker.current; let isExternalSymbol = false; const leftMost = getLeftMostPropertyAccessExpression(type); if (leftMost) { //$todo Flow has problems when switching variables instead of literals const leftMostSymbol = typeChecker.getSymbolAtLocation(leftMost); // todo(flow->ts) const decl = leftMostSymbol ? leftMostSymbol.declarations[0] : {}; isExternalSymbol = decl.kind === ts.SyntaxKind.NamespaceImport || decl.kind === ts.SyntaxKind.NamedImports; } if (!symbol || typeChecker.isUnknownSymbol(symbol) || isExternalSymbol) { return printPropertyAccessExpression(type); } if (((_symbol$parent = symbol.parent) == null ? void 0 : (_symbol$parent$valueD = _symbol$parent.valueDeclaration) == null ? void 0 : _symbol$parent$valueD.kind) === ts.SyntaxKind.SourceFile || ((_symbol$parent2 = symbol.parent) == null ? void 0 : (_symbol$parent2$value = _symbol$parent2.valueDeclaration) == null ? void 0 : _symbol$parent2$value.kind) === ts.SyntaxKind.ModuleDeclaration && (((_symbol$parent3 = symbol.parent) == null ? void 0 : _symbol$parent3.valueDeclaration.flags) & ts.NodeFlags.Namespace) === 0) { return typeChecker.symbolToString(symbol); } // if ( // (symbol.flags & ts.SymbolFlags.ValueModule) === // ts.SymbolFlags.ValueModule // ) { // return typeChecker.symbolToString( // symbol, // undefined, // /*meaning*/ undefined, // ts.SymbolFormatFlags.DoNotIncludeSymbolChain | // ts.SymbolFormatFlags.AllowAnyNodeKind, // ); // } return symbol.parent ? getFullyQualifiedPropertyAccessExpression(symbol.parent, type, delimiter) + delimiter + typeChecker.symbolToString(symbol) : typeChecker.symbolToString(symbol, undefined, /*meaning*/ undefined, //$todo Some problem about TypeScript enums conversion and bitwise operators ts.SymbolFormatFlags.DoNotIncludeSymbolChain | ts.SymbolFormatFlags.AllowAnyNodeKind); } else { return printPropertyAccessExpression(type); } } function getFullyQualifiedName(symbol, type, checks = true, delimiter = "$") { if (_checker.checker.current) { var _symbol$parent4, _symbol$parent4$value, _symbol$parent5, _symbol$parent5$value, _symbol$parent6, _symbol$valueDeclarat; const typeChecker = _checker.checker.current; if (checks) { let isExternalSymbol = false; const leftMost = (0, _smartIdentifiers.getLeftMostEntityName)(type); if (leftMost) { var _leftMostSymbol$paren; //$todo Flow has problems when switching variables instead of literals const leftMostSymbol = typeChecker.getSymbolAtLocation(leftMost); const decl = leftMostSymbol && leftMostSymbol.declarations && leftMostSymbol.declarations.length ? leftMostSymbol.declarations[0] : {}; isExternalSymbol = decl.kind === ts.SyntaxKind.NamespaceImport || decl.kind === ts.SyntaxKind.NamedImports || decl.kind === ts.SyntaxKind.TypeParameter || (leftMostSymbol == null ? void 0 : (_leftMostSymbol$paren = leftMostSymbol.parent) == null ? void 0 : _leftMostSymbol$paren.escapedName) === "__global"; } if (!symbol || typeChecker.isUnknownSymbol(symbol) || isExternalSymbol) { return printEntityName(type); } } if (((_symbol$parent4 = symbol.parent) == null ? void 0 : (_symbol$parent4$value = _symbol$parent4.valueDeclaration) == null ? void 0 : _symbol$parent4$value.kind) === ts.SyntaxKind.SourceFile || ((_symbol$parent5 = symbol.parent) == null ? void 0 : (_symbol$parent5$value = _symbol$parent5.valueDeclaration) == null ? void 0 : _symbol$parent5$value.kind) === ts.SyntaxKind.ModuleDeclaration && (((_symbol$parent6 = symbol.parent) == null ? void 0 : _symbol$parent6.valueDeclaration.flags) & ts.NodeFlags.Namespace) === 0) { return typeChecker.symbolToString(symbol); } // if ( // (symbol.flags & ts.SymbolFlags.ValueModule) === // ts.SymbolFlags.ValueModule // ) { // return typeChecker.symbolToString( // symbol, // undefined, // /*meaning*/ undefined, // ts.SymbolFormatFlags.DoNotIncludeSymbolChain | // ts.SymbolFormatFlags.AllowAnyNodeKind, // ); // } if (((_symbol$valueDeclarat = symbol.valueDeclaration) == null ? void 0 : _symbol$valueDeclarat.kind) === ts.SyntaxKind.EnumMember) delimiter = "."; return symbol.parent ? getFullyQualifiedName(symbol.parent, type, true, delimiter) + delimiter + typeChecker.symbolToString(symbol) : typeChecker.symbolToString(symbol, undefined, /*meaning*/ undefined, //$todo Some problem about TypeScript enums conversion and bitwise operators ts.SymbolFormatFlags.DoNotIncludeSymbolChain | ts.SymbolFormatFlags.AllowAnyNodeKind); } else { return printEntityName(type); } } function getTypeofFullyQualifiedName(symbol, type, delimiter = ".") { if (_checker.checker.current) { var _symbol$parent7, _symbol$parent7$value, _symbol$parent8, _symbol$parent8$value, _symbol$parent9, _symbol$parent10; const typeChecker = _checker.checker.current; let isExternalSymbol = false; const leftMost = (0, _smartIdentifiers.getLeftMostEntityName)(type); if (leftMost) { //$todo Flow has problems when switching variables instead of literals const leftMostSymbol = typeChecker.getSymbolAtLocation(leftMost); // todo(flow->ts) const decl = leftMostSymbol ? leftMostSymbol.declarations[0] : {}; isExternalSymbol = decl.kind === ts.SyntaxKind.NamespaceImport || decl.kind === ts.SyntaxKind.NamedImports; } if (!symbol || typeChecker.isUnknownSymbol(symbol) || isExternalSymbol) { return printEntityName(type); } if (((_symbol$parent7 = symbol.parent) == null ? void 0 : (_symbol$parent7$value = _symbol$parent7.valueDeclaration) == null ? void 0 : _symbol$parent7$value.kind) === ts.SyntaxKind.SourceFile || ((_symbol$parent8 = symbol.parent) == null ? void 0 : (_symbol$parent8$value = _symbol$parent8.valueDeclaration) == null ? void 0 : _symbol$parent8$value.kind) === ts.SyntaxKind.ModuleDeclaration && (((_symbol$parent9 = symbol.parent) == null ? void 0 : _symbol$parent9.valueDeclaration.flags) & ts.NodeFlags.Namespace) === 0) { return typeChecker.symbolToString(symbol); } if (((_symbol$parent10 = symbol.parent) == null ? void 0 : _symbol$parent10.escapedName) === "__type") { return symbol.parent ? getTypeofFullyQualifiedName( // @ts-expect-error todo(flow->ts) symbol.parent.declarations[0].parent.symbol, type) + delimiter + typeChecker.symbolToString(symbol) : typeChecker.symbolToString(symbol, undefined, /*meaning*/ undefined, //$todo Some problem about TypeScript enums conversion and bitwise operators ts.SymbolFormatFlags.DoNotIncludeSymbolChain | ts.SymbolFormatFlags.AllowAnyNodeKind); } else { var _symbol$valueDeclarat2; let delimiter = "$"; if (((_symbol$valueDeclarat2 = symbol.valueDeclaration) == null ? void 0 : _symbol$valueDeclarat2.kind) === ts.SyntaxKind.EnumMember) { delimiter = "."; } return symbol.parent ? getTypeofFullyQualifiedName(symbol.parent, type, delimiter) + delimiter + typeChecker.symbolToString(symbol) : typeChecker.symbolToString(symbol, undefined, /*meaning*/ undefined, //$todo Some problem about TypeScript enums conversion and bitwise operators ts.SymbolFormatFlags.DoNotIncludeSymbolChain | ts.SymbolFormatFlags.AllowAnyNodeKind); } } else { return printEntityName(type); } } function printFlowGenHelper(env) { let helpers = ""; if (env.conditionalHelpers) { helpers += ` // see https://gist.github.com/thecotne/6e5969f4aaf8f253985ed36b30ac9fe0 type $FlowGen$If<X: boolean, Then, Else = empty> = $Call< & ((true, Then, Else) => Then) & ((false, Then, Else) => Else), X, Then, Else, >; type $FlowGen$Assignable<A, B> = $Call< & ((...r: [B]) => true) & ((...r: [A]) => false), A, >;`; } return helpers; } function fixDefaultTypeArguments(symbol, type) { var _decl$typeParameters; if (!symbol) return; if (!symbol.declarations) return; const decl = symbol.declarations[0]; const allTypeParametersHaveDefaults = // @ts-expect-error todo(flow->ts) !!(decl != null && (_decl$typeParameters = decl.typeParameters) != null && _decl$typeParameters.length) && // @ts-expect-error todo(flow->ts) decl.typeParameters.every(param => !!param.default); if (allTypeParametersHaveDefaults && !type.typeArguments) { type.typeArguments = []; } } /** * Log an error, while returning a commented FlowFixMe type. * * This is appropriate for error conditions that indicate a bug within * Flowgen. * * The error uses `logger.error` for a nice message pointing at the input * source code corresponding to `node`, to help identify what triggered the * issue. */ const printErrorType = (description, node) => { logger.error(node, { type: "FlowgenInternalError", description }); return `($FlowFixMe /* flowgen-error: ${description} */)`; }; const printType = (0, _env.withEnv)((env, rawType) => { var _type$name, _name, _type$name2; // debuggerif() //TODO: #6 No match found in SyntaxKind enum const type = rawType; const keywordPrefix = // @ts-expect-error todo(flow->ts) type.modifiers && // @ts-expect-error todo(flow->ts) type.modifiers.some(modifier => modifier.kind === ts.SyntaxKind.StaticKeyword) ? "static " : ""; const kind = ts.SyntaxKind[type.kind].toString(); switch (type.kind) { case ts.SyntaxKind.VoidKeyword: return printers.basics.print(kind); case ts.SyntaxKind.StringKeyword: return printers.basics.print(kind); case ts.SyntaxKind.AnyKeyword: return printers.basics.print(kind); case ts.SyntaxKind.NumberKeyword: return printers.basics.print(kind); case ts.SyntaxKind.BooleanKeyword: return printers.basics.print(kind); case ts.SyntaxKind.NullKeyword: return printers.basics.print(kind); case ts.SyntaxKind.UndefinedKeyword: return printers.basics.print(kind); case ts.SyntaxKind.ObjectKeyword: return printers.basics.print(kind); case ts.SyntaxKind.FalseKeyword: return printers.basics.print(kind); case ts.SyntaxKind.TrueKeyword: return printers.basics.print(kind); case ts.SyntaxKind.NeverKeyword: return printers.basics.print(kind); case ts.SyntaxKind.UnknownKeyword: return printers.basics.print(kind); case ts.SyntaxKind.SymbolKeyword: // TODO: What to print here? return "Symbol"; case ts.SyntaxKind.BigIntKeyword: return printers.basics.print(kind); // JSDoc types case ts.SyntaxKind.JSDocAllType: return "*"; case ts.SyntaxKind.JSDocUnknownType: return "?"; case ts.SyntaxKind.JSDocOptionalType: return printType(type.type) + "="; case ts.SyntaxKind.JSDocFunctionType: { const params = type.parameters.map(param => printType(param.type)).join(", "); const ret = type.type ? `: ${printType(type.type)}` : ""; return `function(${params})${ret}`; } case ts.SyntaxKind.JSDocTypeLiteral: return "object"; case ts.SyntaxKind.JSDocVariadicType: return "..." + printType(type.type); case ts.SyntaxKind.JSDocNonNullableType: return "!" + printType(type.type); case ts.SyntaxKind.JSDocNullableType: return "?" + printType(type.type); case ts.SyntaxKind.JSDocNameReference: // @ts-expect-error todo(flow->ts) - 'escapedText' does not exist on type 'EntityName | JSDocMemberName' return (type == null ? void 0 : (_type$name = type.name) == null ? void 0 : _type$name.escapedText) || ""; case ts.SyntaxKind.ConditionalType: { env.conditionalHelpers = true; return `$FlowGen$If<$FlowGen$Assignable<${printType(type.checkType)},${printType(type.extendsType)}>,${printType(type.trueType)},${printType(type.falseType)}>`; } case ts.SyntaxKind.ComputedPropertyName: { var _type$expression, _type$expression$expr, _type$expression2, _type$expression2$nam, _type$expression3, _type$expression3$exp, _type$expression4, _type$expression4$nam; if ( // @ts-expect-error todo(flow->ts) ((_type$expression = type.expression) == null ? void 0 : (_type$expression$expr = _type$expression.expression) == null ? void 0 : _type$expression$expr.text) === "Symbol" && // @ts-expect-error todo(flow->ts) ((_type$expression2 = type.expression) == null ? void 0 : (_type$expression2$nam = _type$expression2.name) == null ? void 0 : _type$expression2$nam.text) === "iterator") { return "@@iterator"; } if ( // @ts-expect-error todo(flow->ts) ((_type$expression3 = type.expression) == null ? void 0 : (_type$expression3$exp = _type$expression3.expression) == null ? void 0 : _type$expression3$exp.text) === "Symbol" && // @ts-expect-error todo(flow->ts) ((_type$expression4 = type.expression) == null ? void 0 : (_type$expression4$nam = _type$expression4.name) == null ? void 0 : _type$expression4$nam.text) === "asyncIterator") { return "@@asyncIterator"; } if (type.expression.kind === ts.SyntaxKind.StringLiteral) { return printType(type.expression); } logger.error(type.expression, { type: "UnsupportedComputedProperty" }); return `[typeof ${printType(type.expression)}]`; } case ts.SyntaxKind.FunctionType: //case SyntaxKind.FunctionTypeAnnotation: return printers.functions.functionType(type); case ts.SyntaxKind.TypeLiteral: return printers.declarations.interfaceType(type, "", [], false, true); //case SyntaxKind.IdentifierObject: //case SyntaxKind.StringLiteralType: case ts.SyntaxKind.Identifier: { return printers.relationships.namespace( // @ts-expect-error todo(flow->ts) printers.identifiers.print(type.text), true); } case ts.SyntaxKind.BindingElement: // @ts-expect-error todo(flow->ts) return printers.common.typeParameter(type); case ts.SyntaxKind.TypeParameter: // @ts-expect-error todo(flow->ts) return printers.common.typeParameter(type); case ts.SyntaxKind.PrefixUnaryExpression: switch (type.operator) { case ts.SyntaxKind.MinusToken: // @ts-expect-error todo(flow->ts) return `-${type.operand.text}`; default: console.log('"NO PRINT IMPLEMENTED: PrefixUnaryExpression"'); return '"NO PRINT IMPLEMENTED: PrefixUnaryExpression"'; } case ts.SyntaxKind.TypePredicate: //TODO: replace with boolean %checks when supported in class declarations return "boolean"; case ts.SyntaxKind.IndexedAccessType: { let fn = "$ElementType"; if (ts.isLiteralTypeNode(type.indexType) && type.indexType.literal.kind === ts.SyntaxKind.StringLiteral) { fn = "$PropertyType"; } return `${fn}<${printType(type.objectType)}, ${printType(type.indexType)}>`; } case ts.SyntaxKind.TypeOperator: switch (type.operator) { case ts.SyntaxKind.KeyOfKeyword: return `$Keys<${printType(type.type)}>`; case ts.SyntaxKind.UniqueKeyword: logger.error(type, { type: "UnsupportedUniqueSymbol" }); return printType(type.type); case ts.SyntaxKind.ReadonlyKeyword: if (ts.isArrayTypeNode(type.type)) { return `$ReadOnlyArray<${printType(type.type.elementType)}>`; } else if (type.type.kind === ts.SyntaxKind.TupleType) { return printType(type.type); } else { const error = { type: "UnsupportedTypeOperator", operator: type.operator }; logger.error(type, error); return `/* ${(0, _errorMessage.printErrorMessage)(error)} */ any`; } default: { const error = { type: "UnsupportedTypeOperator", // @ts-expect-error operator: type.operator }; logger.error(type, error); return `/* ${(0, _errorMessage.printErrorMessage)(error)} */ any`; } } case ts.SyntaxKind.MappedType: { const constraint = type.typeParameter.constraint; const typeName = printType(type.typeParameter.name); const value = printType(type.type); let source = `{[k: ${printType(constraint)}]: any}`; // @ts-expect-error todo(flow->ts) if (constraint.operator === ts.SyntaxKind.KeyOfKeyword) { // @ts-expect-error todo(flow->ts) source = printType(constraint.type); } return `$ObjMapi<${source}, <${typeName}>(${typeName}) => ${value}>`; } case ts.SyntaxKind.BigIntLiteral: return type.text; case ts.SyntaxKind.FirstLiteralToken: // @ts-expect-error todo(flow->ts) return type.text; case ts.SyntaxKind.ImportType: return printErrorType("Failed to transform an ImportType node", type); case ts.SyntaxKind.FirstTypeNode: return printers.common.literalType(type); case ts.SyntaxKind.LastTypeNode: return printers.common.literalType(type); case ts.SyntaxKind.LiteralType: return printers.common.literalType(type); case ts.SyntaxKind.QualifiedName: { let symbol; if (_checker.checker.current) { //$todo symbol = _checker.checker.current.getSymbolAtLocation(type); } return getFullyQualifiedName(symbol, type); } case ts.SyntaxKind.StringLiteral: return JSON.stringify(type.text); case ts.SyntaxKind.TypeReference: { let symbol; if (_checker.checker.current) { symbol = _checker.checker.current.getSymbolAtLocation(type.typeName); //$todo fixDefaultTypeArguments(symbol, type); const isRenamed = (0, _smartIdentifiers.renames)(symbol, type); if (!isRenamed) { //$todo weird union errors // @ts-expect-error todo(flow->ts) type.typeName.escapedText = getFullyQualifiedName(symbol, type.typeName); } const getAdjustedType = targetSymbol => { const isTypeImport = symbol && symbol.declarations && symbol.declarations[0] && ts.isTypeOnlyImportOrExportDeclaration(symbol.declarations[0]); if (targetSymbol && targetSymbol.declarations && targetSymbol.declarations[0].kind === ts.SyntaxKind.EnumMember) { return `${isTypeImport ? "" : "typeof"} ${getTypeofFullyQualifiedName(targetSymbol, type.typeName)}`; } else if (targetSymbol && targetSymbol.declarations && targetSymbol.declarations[0].kind === ts.SyntaxKind.EnumDeclaration) { return `$Values< ${isTypeImport ? "" : "typeof "} ${getTypeofFullyQualifiedName(targetSymbol, type.typeName)}>`; } return printers.declarations.typeReference(type, !targetSymbol); }; // if importing an enum, we have to change how the type is used across the file if (symbol && symbol.declarations && symbol.declarations[0].kind === ts.SyntaxKind.ImportSpecifier) { return getAdjustedType(_checker.checker.current.getTypeAtLocation(type).symbol); } else { return getAdjustedType(symbol); } } return printers.declarations.typeReference(type, !symbol); } case ts.SyntaxKind.VariableDeclaration: return printers.declarations.propertyDeclaration(type, keywordPrefix); case ts.SyntaxKind.PropertyDeclaration: return printers.declarations.propertyDeclaration(type, keywordPrefix); //$todo some weird union errors case ts.SyntaxKind.OptionalType: return `${printType(type.type)} | void`; case ts.SyntaxKind.TupleType: { const lastElement = type.elements[type.elements.length - 1]; if (lastElement && ts.isRestTypeNode(lastElement)) // @ts-expect-error todo(flow->ts) type.elements.pop(); let tuple = `[${type.elements.map(printType).join(", ")}]`; if (lastElement && ts.isRestTypeNode(lastElement)) { tuple += ` & ${printType(lastElement.type)}`; } return tuple; } case ts.SyntaxKind.MethodSignature: return printers.common.methodSignature(type); case ts.SyntaxKind.ExpressionWithTypeArguments: return printType(type.expression) + printers.common.generics(type.typeArguments); case ts.SyntaxKind.PropertyAccessExpression: return getFullyQualifiedPropertyAccessExpression( //$todo some weird union errors _checker.checker.current.getSymbolAtLocation(type), type); // case SyntaxKind.NodeObject: // return ( // printers.relationships.namespace(type.expression.text) + // printType(type.name) // ); case ts.SyntaxKind.PropertySignature: return printers.common.parameter(type); case ts.SyntaxKind.CallSignature: { // TODO: rewrite to printers.functions.functionType const generics = printers.common.genericsWithoutDefault(type.typeParameters); const str = `${generics}(${type.parameters // @ts-expect-error todo(flow->ts) .filter(param => param.name.text !== "this").map(printers.common.parameter).join(", ")})`; // TODO: I can't understand this return type.type ? `${str}: ${printType(type.type)}` : `${str}: any`; } case ts.SyntaxKind.UnionType: { const join = type.types.length >= 5 ? "\n" : " "; // debugger return type.types.map(printType).join(`${join}| `); } case ts.SyntaxKind.ArrayType: return printType(type.elementType) + "[]"; case ts.SyntaxKind.ThisType: return "this"; case ts.SyntaxKind.IndexSignature: if (type.type) { return `[${type.parameters.map(printers.common.parameter).join(", ")}]: ${printType(type.type)}`; } return ""; case ts.SyntaxKind.IntersectionType: { // for non-class types, we can't easily just merge types together using & // this is because in Typescript // { a: number } & { b: string} // is NOT equivalent to {| a: number |} & {| b: string |} in Flow // since you can't intersect exact types in Flow // https://github.com/facebook/flow/issues/4946#issuecomment-331520118 // instead, you have to use the spread notation // HOWEVER, you must use & to intersect classes (you can't spread a class) const containsClass = type.types.map(_checker.checker.current.getTypeAtLocation).find(type => type.isClass()); if (containsClass) { return type.types.map(printType).join(" & "); } const spreadType = type.types.map(type => `...${printType(type)}`).join(","); const isInexact = (0, _options.opts)().inexact; return isInexact ? `{ ${spreadType} }` : `{| ${spreadType} |}`; } case ts.SyntaxKind.MethodDeclaration: // Skip methods marked as private if (type.modifiers && type.modifiers.some(modifier => modifier.kind === ts.SyntaxKind.PrivateKeyword)) { return ""; } return keywordPrefix + printers.common.methodSignature(type); case ts.SyntaxKind.ConstructorType: // Not implemented. The return is just a guess. return "(" + type.parameters.map(printers.common.parameter).join(", ") + ") => " + printType(type.type); case ts.SyntaxKind.ConstructSignature: return "new " + printers.functions.functionType(type, true); case ts.SyntaxKind.TypeQuery: { //$todo some weird union errors const symbol = _checker.checker.current.getSymbolAtLocation(type.exprName); return "typeof " + getTypeofFullyQualifiedName(symbol, type.exprName); } case ts.SyntaxKind.Constructor: return "constructor(" + type.parameters.map(printers.common.parameter).join(", ") + "): this"; case ts.SyntaxKind.ParenthesizedType: return `(${printType(type.type)})`; case ts.SyntaxKind.ImportSpecifier: if (_checker.checker.current) { //$todo some weird union errors const symbol = _checker.checker.current.getSymbolAtLocation(type.name); (0, _smartIdentifiers.renames)(symbol, type); } return printers.relationships.importExportSpecifier(type); case ts.SyntaxKind.ExportSpecifier: return printers.relationships.importExportSpecifier(type); case ts.SyntaxKind.GetAccessor: return keywordPrefix + printers.common.parameter(type); case ts.SyntaxKind.SetAccessor: return printers.common.parameter(type); case ts.SyntaxKind.InferType: return printType(type.typeParameter); default: } console.log(` ts.SyntaxKind[type.kind]: ${ts.SyntaxKind[type.kind]} name: ${type == null ? void 0 : (_name = type.name) == null ? void 0 : _name.escapedText} kind: ${type.kind} type: ${_util.default.inspect(type)} `); // @ts-expect-error todo(flow->ts) const output = `${(_type$name2 = type.name) == null ? void 0 : _type$name2.escapedText}: /* NO PRINT IMPLEMENTED: ${// @ts-expect-error todo(flow->ts) ts.SyntaxKind[type.kind]} */ any`; console.log(output); return output; }); exports.printType = printType; var _default = printType; exports.default = _default;