Skip to content
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

TypeScript declared namespaces break when imports are used #13000

Closed
jaydenseric opened this issue Dec 6, 2021 · 3 comments
Closed

TypeScript declared namespaces break when imports are used #13000

jaydenseric opened this issue Dec 6, 2021 · 3 comments
Labels
working as designed this is working as intended

Comments

@jaydenseric
Copy link

jaydenseric commented Dec 6, 2021

A TypeScript declared namespace incorrectly becomes missing when attempting to consume the .d.ts file when the definition file also contains imports.

In this example, Deno incorrectly thinks the namespace Namespace is missing:

Screen Shot 2021-12-06 at 10 47 06 pm

If you comment out the import, the namespace is no longer missing:

Screen Shot 2021-12-06 at 10 47 24 pm

@bartlomieju bartlomieju added the bug Something isn't working correctly label Dec 6, 2021
@bartlomieju
Copy link
Member

CC @kitsonk @dsherret might this be related to recent troubles in SWC?

@kitsonk kitsonk added working as designed this is working as intended and removed bug Something isn't working correctly labels Dec 6, 2021
@kitsonk
Copy link
Contributor

kitsonk commented Dec 6, 2021

No, Deno is working correctly...

When you have a type definition and you import or export from it, it becomes a module instead of an ambient declaration. Therefore the namespace is scoped to the module and any declaration are scoped to the module.

You would need to either export and import the namespace, or declare the namespace globally:

declare global {
  namespace Namespace {
    export type A = boolean;
  }
}

@jaydenseric
Copy link
Author

jaydenseric commented Dec 7, 2021

Thanks @kitsonk for your comment, trying to get this working is a nightmare of footguns. Nothing is intuitive about how any of this works. Because all the tooling is so buggy, when something doesn't work it's hard to tell if it's because you're doing something wrong and should reevaluate the approach or if it's just broken.

There's no clear examples for the ideal way to work with JSDoc types both as a package publisher and consumer. At this point, it seems global namespaces "imported" via triple slash references is the only way to work since there is no way to declare types when importing within a JSDoc type. Perhaps the solution is to use JSDoc inline import() types when the type is a real export of a module, and if it's just a type it should be "imported" via a triple slash reference that exposes a namespace holding all the types, which can then be referenced via the namespace in JSDoc types.

A problem is, which triple slash reference is the right one to use? /// <reference types="./foo.d.ts" /> vs /// <reference path="./foo.d.ts" />. The Deno docs on types only mentions types=, and also if you use path= Deno lint gets angry:

Screen Shot 2021-12-07 at 11 11 23 am

Deno lint has been wrong about triple slash references before, so I don't know if the warning can be trusted. But isn't path= the right choice? It seems to work better in experimentation.

Another problem is, even if you know the right way to structure this from the consumer side, how do you compose the .d.ts files to reciprocate it? You need .d.ts files declaring the modules and what they are exporting, but how do you seperate out just the types into a seperate .d.ts file so they can be imported in both the module declaration .d.ts file but also triple slash reference exposed as a namespace in consumer JS modules?

So even if we know the right way to structure all this both from the publisher and consumer side, how can a consumer work with third party .d.ts files that are not carefully composed the right way? In my experimenting .d.ts files when triple slash referenced can corrupt each other when they were originally intended to be defining a particular module's exports. How can you extract just the types out into a namespace safe to triple slash reference in a JS module?

Please help wake me from this nightmare.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
working as designed this is working as intended
Projects
None yet
Development

No branches or pull requests

3 participants