Repository: TypeScript
Issue: Allow namespace declaration merging for all objects
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

Declaration merging, variable, object

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

In TypeScript this is allowed:
```ts
export function someFunction() {
    // some code ...
}

export namespace someFunction {
    export const someVariable = "someValue"
}
```
And this is the JavaScript output:
```js
exports.someFunction = void 0;
function someFunction() {
    // some code ...
}
exports.someFunction = someFunction;
(function (someFunction) {
    someFunction.someVariable = "someValue";
})(someFunction = exports.someFunction || (exports.someFunction = {}));
```
But this "throws" an `error TS2300`:
```ts
export var someObject = { someField: "anotherValue" };

export namespace someObject {
    export const someVariable = "someValue"
}
```
Regardless of the fact that the JavaScript output is actually what I would expect:
```js
exports.someObject = void 0;
exports.someObject = { someField: "anotherValue" };
var someObject;
(function (someObject) {
    someObject.someVariable = "someValue";
})(someObject = exports.someObject || (exports.someObject = {}));
```
And so is its result:
```js
console.log(exports.someObject) //→ {someField: 'anotherValue', someVariable: 'someValue'}
```

<!-- A summary of what you'd like to see added or changed -->

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->

I wanted to define an extensible pipeline of operations.
Those operations need to be executed in a specific order and be accessible separately by name.
This is a simplified example:
```ts
export var pipeline: ((x: string) => string)[] = [];

export namespace pipeline {
    export const spacesToPlus = pipeline[pipeline.length] = x => x.replace(/\s+/g, "+");
    export const addParenthesis = pipeline[pipeline.length] = x => `(${ x })`;
    // ...

    export function execute(x: string) {
        return pipeline.reduce((v, f) => f(v), x);
    }
}

var processedString = pipeline.execute("this is  a    sentence"); // The value is "(this+is+a+sentence)"
var STP = pipeline.spacesToPlus; // Can access each function by name
var firstThing = pipeline[0]; // Can access each function by its execution order

// Can extend the pipeline
export namespace pipeline {
    export const additionalFunctionality = x => {
        console.log(x);
        return x + "...";
    };

    pipeline.splice(pipeline.indexOf(pipeline.spacesToPlus), 0, additionalFunctionality); // "additionalFunctionality" will be inserted after "spacesToPlus" but before "addParenthesis"
}

var secondProcessedString = pipeline.execute("this is  a    sentence"); // The value is "(this+is+a+sentence...)" and the console output is "this+is+a+sentence"
```
This code gets compiled and works as espected, but still "throws" an `error TS2300`

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->
My objective was to create an object which is both a valid array and a namespace. The reason I wanted to do it with a namespace is because it allows me to define both the array elements and the keys at the same time (Both in the type and the runtime object) and easily merge all the partial definitions of the namespace. Since it is phisically possible to merge a namespace to every object type I wonder why it is not allowed