Skip to content

Allow namespace declaration merging for all objects #51417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 tasks done
AFatNiBBa opened this issue Nov 5, 2022 · 0 comments
Open
5 tasks done

Allow namespace declaration merging for all objects #51417

AFatNiBBa opened this issue Nov 5, 2022 · 0 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@AFatNiBBa
Copy link

AFatNiBBa commented Nov 5, 2022

Suggestion

πŸ” Search Terms

Declaration merging, variable, object

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

In TypeScript this is allowed:

export function someFunction() {
    // some code ...
}

export namespace someFunction {
    export const someVariable = "someValue"
}

And this is the JavaScript output:

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:

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:

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:

console.log(exports.someObject) //β†’ {someField: 'anotherValue', someVariable: 'someValue'}

πŸ“ƒ Motivating Example

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:

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants