From 447428b5c37922444cdb1e4a8bbca6301ee6d8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Kn=C3=B6chel?= Date: Tue, 19 Aug 2025 10:25:03 +0200 Subject: [PATCH 1/2] fix: properly handle promise generics --- .../generators/typescript_generator.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/titanium-docgen/generators/typescript_generator.js b/packages/titanium-docgen/generators/typescript_generator.js index 0518e93..1d4234b 100644 --- a/packages/titanium-docgen/generators/typescript_generator.js +++ b/packages/titanium-docgen/generators/typescript_generator.js @@ -175,7 +175,9 @@ class DocsParser { // skip bundled documentation for modules and Node.js shims return; } - const namespaceParts = typeInfo.name.split('.'); + // Handle generic types by extracting the base type name before the first '<' + const typeName = typeInfo.name.split('<')[0]; + const namespaceParts = typeName.split('.'); namespaceParts.pop(); if (skipApis.includes(typeInfo.name)) { return; @@ -622,7 +624,17 @@ class GlobalTemplateWriter { if (Array.isArray(docType)) { const normalizedTypes = docType.map(typeName => this.normalizeType(typeName)); - return normalizedTypes.includes('any') ? 'any' : normalizedTypes.join(' | '); + if (normalizedTypes.includes('any')) { + return 'any'; + } + // Parenthesize function types in unions to avoid TypeScript syntax errors + const parenthesizedTypes = normalizedTypes.map(type => { + if (type.includes(') => ')) { + return `(${type})`; + } + return type; + }); + return parenthesizedTypes.join(' | '); } const lessThanIndex = docType.indexOf('<'); @@ -649,6 +661,9 @@ class GlobalTemplateWriter { } } else if (baseType === 'Dictionary') { return `Dictionary<${subType}>`; + } else if (baseType === 'Promise') { + // Use standard Promise generic syntax + return `Promise<${subTypes.join(', ')}>`; } } From 2afeb59c0857ce0b8286080ae9c4aa67183b9f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Kn=C3=B6chel?= Date: Tue, 19 Aug 2025 10:43:54 +0200 Subject: [PATCH 2/2] fix: do not throw error regarding generic promises --- packages/titanium-docgen/validate.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/titanium-docgen/validate.js b/packages/titanium-docgen/validate.js index 3c4c17b..f879773 100644 --- a/packages/titanium-docgen/validate.js +++ b/packages/titanium-docgen/validate.js @@ -434,8 +434,12 @@ function validateDataType(type, fullTypeContext) { // Should it have been written as a complex type? if (common.COMPLEX_TYPES.has(type)) { const argCount = common.COMPLEX_TYPES.get(type); // may be 0 if Function/Callback - // Enforce as ERROR if Promise/Set/Map doesn't have exact generic type count - const severity = [ 'Map', 'Set', 'Promise' ].includes(type) ? ERROR : WARNING; + // Skip validation for Promise to allow Promise without generics (Promise not supported by build system) + if (type === 'Promise') { + return errors; + } + // Enforce as ERROR if Set/Map doesn't have exact generic type count + const severity = [ 'Map', 'Set' ].includes(type) ? ERROR : WARNING; errors.push(new Problem(`${type} ${severity === ERROR ? 'must' : 'should'} have ${argCount || 'any number of'} generic type(s) specified, but had 0: ${fullTypeContext || type}`, severity)); } else if (type === 'Object') { // Warn about generic Object types (Dictionary is handled above as a complex type)