tc39 / proposal-module-declarations

JavaScript Module Declarations
https://tc39.es/proposal-module-declarations
MIT License
369 stars 7 forks source link

Declaration merging #28

Open aspirisen opened 1 year ago

aspirisen commented 1 year ago

Hello, will it be possible to merge declarations, like that:

module Hello {
    export const A = 3;
}

module Hello {
    export const B = 4;
}

console.log(Hello.A, Hello.B) // 3, 4

This is how namespaces works in typescript (previously they called modules). Playground

One huge benefit of namespaces is that they can be merge with functions declarations. Playground

function Hello() {
    return 3
}

namespace Hello {
    export const meta = 4
}

console.log(Hello(), Hello.meta) // 3, 4

This is a widely used pattern i.e. in react. Playground

export function Component(props: PropsWithChildren) {
    return <div>{props.children}</div>
}

export namespace Component {
    export function Icon() {
        return <i className="icon" />
    }
}
ljharb commented 1 year ago

That's the major reason I avoid namespaces in TS - the Ruby-esque ability to reopen and edit a definition in my experience makes code much harder to reason about.

If you want to compose modules, imo you should use the current tools and import + re-export, rather than smooshing the code together.

aspirisen commented 1 year ago

@ljharb merging modules is just one of the possibilities, anyway they will be in one file. Actually, I've never used namespaces merging in TypeScript.

But merging namespace with function is pretty common use case to add logically related things to the function. Probably this will be the target use case for declaration merging. Yes, you will be able to merge modules by that way, but I can hardly imagine why one will need it since everything is in the same file.

Vasile-Peste commented 1 year ago

That's the major reason I avoid namespaces in TS - the Ruby-esque ability to reopen and edit a definition in my experience makes code much harder to reason about.

If you want to compose modules, imo you should use the current tools and import + re-export, rather than smooshing the code together.

What if we optionally declare if a module can be merged? Something like partial classes in C#. This makes the reader aware that some members of the module might come from other merged declarations.

// ok
partial module A {
    export const foo = ...;
}

// ok
partial module A {
    export const bar = ...;
}
// ok
module A {
    export const foo = ...;
}

// Redeclaration error
module A {
    export const bar = ...;
}

Reference https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods

littledan commented 1 year ago

This proposal does not permit merging. The code sample at the beginning of the thread would cause an error at parse time. (However, this is not meant to pass judgement on TS declaration merging, which I don’t know if the world could live without!)