diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 9732458c7a9..6a9cb08fa7c 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -574,6 +574,16 @@ namespace ts { return false; } + // If the ExpandoFunctionDeclaration have multiple overloads, then we only need to emit properties for the last one. + function shouldEmitFunctionProperties(input: FunctionDeclaration) { + if (input.body) { + return true; + } + + const overloadSignatures = input.symbol.declarations?.filter(decl => isFunctionDeclaration(decl) && !decl.body); + return !overloadSignatures || overloadSignatures.indexOf(input) === overloadSignatures.length - 1; + } + function getBindingNameVisible(elem: BindingElement | VariableDeclaration | OmittedExpression): boolean { if (isOmittedExpression(elem)) { return false; @@ -1194,7 +1204,7 @@ namespace ts { ensureType(input, input.type), /*body*/ undefined )); - if (clean && resolver.isExpandoFunctionDeclaration(input)) { + if (clean && resolver.isExpandoFunctionDeclaration(input) && shouldEmitFunctionProperties(input)) { const props = resolver.getPropertiesOfContainerFunction(input); // Use parseNodeFactory so it is usable as an enclosing declaration const fakespace = parseNodeFactory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace); diff --git a/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.js b/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.js new file mode 100644 index 00000000000..c32276096db --- /dev/null +++ b/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.js @@ -0,0 +1,23 @@ +//// [declarationEmitFunctionDuplicateNamespace.ts] +function f(a: 0): 0; +function f(a: 1): 1; +function f(a: 0 | 1) { + return a; +} + +f.x = 2; + + +//// [declarationEmitFunctionDuplicateNamespace.js] +function f(a) { + return a; +} +f.x = 2; + + +//// [declarationEmitFunctionDuplicateNamespace.d.ts] +declare function f(a: 0): 0; +declare function f(a: 1): 1; +declare namespace f { + var x: number; +} diff --git a/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.symbols b/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.symbols new file mode 100644 index 00000000000..75ff9f9d4e0 --- /dev/null +++ b/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.symbols @@ -0,0 +1,22 @@ +=== tests/cases/compiler/declarationEmitFunctionDuplicateNamespace.ts === +function f(a: 0): 0; +>f : Symbol(f, Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 0), Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 1, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 4, 1)) +>a : Symbol(a, Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 11)) + +function f(a: 1): 1; +>f : Symbol(f, Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 0), Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 1, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 4, 1)) +>a : Symbol(a, Decl(declarationEmitFunctionDuplicateNamespace.ts, 1, 11)) + +function f(a: 0 | 1) { +>f : Symbol(f, Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 0), Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 1, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 4, 1)) +>a : Symbol(a, Decl(declarationEmitFunctionDuplicateNamespace.ts, 2, 11)) + + return a; +>a : Symbol(a, Decl(declarationEmitFunctionDuplicateNamespace.ts, 2, 11)) +} + +f.x = 2; +>f.x : Symbol(f.x, Decl(declarationEmitFunctionDuplicateNamespace.ts, 4, 1)) +>f : Symbol(f, Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 0), Decl(declarationEmitFunctionDuplicateNamespace.ts, 0, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 1, 20), Decl(declarationEmitFunctionDuplicateNamespace.ts, 4, 1)) +>x : Symbol(f.x, Decl(declarationEmitFunctionDuplicateNamespace.ts, 4, 1)) + diff --git a/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.types b/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.types new file mode 100644 index 00000000000..74bd54bcc00 --- /dev/null +++ b/tests/baselines/reference/declarationEmitFunctionDuplicateNamespace.types @@ -0,0 +1,24 @@ +=== tests/cases/compiler/declarationEmitFunctionDuplicateNamespace.ts === +function f(a: 0): 0; +>f : typeof f +>a : 0 + +function f(a: 1): 1; +>f : typeof f +>a : 1 + +function f(a: 0 | 1) { +>f : typeof f +>a : 0 | 1 + + return a; +>a : 0 | 1 +} + +f.x = 2; +>f.x = 2 : 2 +>f.x : number +>f : typeof f +>x : number +>2 : 2 + diff --git a/tests/cases/compiler/declarationEmitFunctionDuplicateNamespace.ts b/tests/cases/compiler/declarationEmitFunctionDuplicateNamespace.ts new file mode 100644 index 00000000000..317f6b7e517 --- /dev/null +++ b/tests/cases/compiler/declarationEmitFunctionDuplicateNamespace.ts @@ -0,0 +1,8 @@ +// @declaration: true +function f(a: 0): 0; +function f(a: 1): 1; +function f(a: 0 | 1) { + return a; +} + +f.x = 2;