Not planned
Description
🔎 Search Terms
declare module
duplicate identifier
5.5
🕗 Version & Regression Information
This issue was introduced in ts 5.5.2. It's still an issue in 5.6.0-dev.20240621. In 5.4.5 it works as expected.
Specifically, this issue was introduced in 5.5.0-dev.20240524
. The last version where this was working as expected was 5.5.0-dev.20240523.
⏯ GitHub reproduction
https://github.com/AlessioGr/tsbug/blob/83e990cdb97d016f13aac969258aa36491dd31b1/src/index.ts#L9-L8
💻 Code
(as linked in the reproduction):
import type { PayloadRequest } from 'payload'
declare module 'payload' {
export interface DatabaseAdapter {
test: string
}
}
🙁 Actual behavior
The code throws the following error in TypeScript 5.5.2 and works in 5.4.5:
src/index.ts:5:22 - error TS2300: Duplicate identifier 'DatabaseAdapter'.
5 export interface DatabaseAdapter {
~~~~~~~~~~~~~~~
node_modules/.pnpm/payload@3.0.0-beta.53_@swc+core@1.6.3_@swc+types@0.1.8_graphql@16.9.0_typescript@5.5.2/node_modules/payload/dist/index.d.ts:199:15
199 export type { DatabaseAdapter, GeneratedTypes, Payload, RequestContext };
~~~~~~~~~~~~~~~
'DatabaseAdapter' was also declared here.
Here is how it is exported from the payload module:
type DatabaseAdapter = BaseDatabaseAdapter;
export type { DatabaseAdapter, GeneratedTypes, Payload, RequestContext };
Strangely, if I export it like this instead, the TypeScript error disappears:
export type { BaseDatabaseAdapter as DatabaseAdapter, GeneratedTypes, Payload, RequestContext };
🙂 Expected behavior
The code should not throw an error / the repo should compile when running npx tsc
.
Additional information about the issue
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
RyanCavanaugh commentedon Jun 21, 2024
This is a correct error that was incorrectly missed before due to a bug. It's not legal to augment a type alias with an interface.
lukasbash commentedon Jun 22, 2024
I am facing the same issue but I do not really get what you mean with regard to a type alias @RyanCavanaugh?
In my example I am working with the mantine component framework and they are providing a type
MantineModalsOverride
specifically exported for module augmentation so that their component can correct use the preferred type definitions.I am using the module augmentation like this:
In their package they are simple exporting it as:
Why should this be intended? How can I correctly augment the type here?
fatcerberus commentedon Jun 22, 2024
You can’t. If they intended the type to be augmented it should have been declared as an interface.
JstnMcBrd commentedon Jun 24, 2024
I have also encountered this problem, but not when augmenting type aliases. TypeScript throws the same "duplicate identifier" error when trying to augment a class.
This example works in 5.4.5, but breaks in 5.5.2. In contrast, interface augmentation still works fine.
Is this also intentional behavior, related to the same bugfix mentioned previously? If so, is this an undocumented breaking change? I know of several packages that rely on class augmentation in their types.
AlessioGr commentedon Jun 24, 2024
@RyanCavanaugh I feel like it might be a good idea to mention this change briefly in the TS changelogs! Not a breaking change since it was a bug, but it would still remove "functionality" people could have depended on before. Would be helpful for them (including me) to know.
Would also be nice to add more clarity in the docs about module augmentation not being allowed for types, as well as mentioning that you cannot override existing properties - maybe here: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#disallowed-merges. It's never explicitly mentioned that types cannot be augmented.
You are right TypeScript was never intended to allow module augmentation on types. And not only that. The previous bug allowed us to do the following things:
To fix this, not only did we have to change them to interfaces, we also had to find a new pattern for what we were trying to do, as it's no longer possible to override properties using module augmentation.
Instead of overriding properties, we had to add new properties using module augmentation, and change whatever accessed those types in our code to conditionally either use the new, augmented types, or the old non-augmented ones.
I'll close this given it's working the way it was intended to work
JstnMcBrd commentedon Jun 24, 2024
I see this issue has been closed. Let me know if I should open a separate issue for the class augmentation problem I mentioned above.
fatcerberus commentedon Jun 24, 2024
I could have sworn I remembered the previous (buggy) behavior being "the augmentation is just silently ignored"...
@JstnMcBrd Documentation explicitly states
AFAIK you can augment a class using an interface, though.
RyanCavanaugh commentedon Jun 24, 2024
See #53287; this usually manifested as a crash because multiple parts of the code rely on the assumption that type aliases and interfaces can't merge.
RyanCavanaugh commentedon Jun 24, 2024
Correct; to add instance properties to a class, use an
interface
merge6mint commentedon Jul 5, 2024
When using a .d.ts file the interface doesn't throw the duplicate identifier error even though it is defined in an installed module. Is this working as intended or is this incorrect behaviour that will be fixed in the future?
The code below works as a .d.ts file but throws as a .ts file:
6 remaining items