We're running into an issue trying to support declaration merging in our library, while exporting the interface behind a export * from "file" as Namespace
. The code works when the declarations are generated via tsc
but not when generated via tsup
.
I've built a reproduction here: https://github.com/Retsam/tsup-declaration-merge-issue-repro
And here's a TS Bug Workbench with just the generated code: Bug Workbench
The relevant code is:
lib/index.ts
:
export * as Mod from "./mod";
lib/mod.ts
// This is meant for declaration merging
export interface EventMap {}
export function addListener<E extends keyof EventMap>(_event: E, _handle: (payload: EventMap[E]) => void) {}
app/index.ts
import { Mod } from "lib";
declare module "lib" {
namespace Mod {
interface EventMap {
myEvent: string;
}
}
}
Mod.addListener("myEvent", (val) => {
console.log(val.toUpperCase());
});
The generated code is:
interface EventMap {}
declare function addListener<E extends keyof EventMap>(_event: E, _handle: (payload: EventMap[E]) => void): void;
type mod_EventMap = EventMap;
declare const mod_addListener: typeof addListener;
declare namespace mod {
export { type mod_EventMap as EventMap, mod_addListener as addListener };
}
export { mod as Mod };
From playing with this, it seems like the declaration merge is modfying the interface inside the namespace, but somehow that's not the same as the one outside the namespace. (I'm not 100% sure this isn't a TS bug) I found that something I could do to 'fix' it (via manually editing the .d.ts
file) was:
interface EventMap {}
-declare function addListener<E extends keyof EventMap>(
+declare function addListener<E extends keyof mod.EventMap>(
_event: E,
- _handle: (payload: EventMap[E]) => void
+ _handle: (payload: mod.EventMap[E]) => void
): void;
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too