-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Merging constants with namespaces #18163
Comments
Just noticed it's been discussed in #18394:
Two options:
Just like when a function declaration is merged with a namespace.
Is it a big deal? When interfaces are being merged, the same thing happens: you're changing random other types.
It's possible, of course, but it's uglier and not DRY. |
that is not true. you are changing the same type. nothing random about it. |
I don't understand what is meant by random. Neither namespaces nor constant declarations create types other than declare const tinymce: tinymce.EditorManager;
declare namespace tinymce {
// ...
} So what is the problem? The discrepancy between the type annotation and the actual type? I feel like you mean something else. |
Okay, I think I got it. "Does this merge with the variable or the type?" was a question with two alternatives. The answer is "the variable", not "the type". In my snippet above, the type |
but that means that |
Can we add some syntax to indicate that the type annotation isn't final? declare const tinymce: tinymce.EditorManager & ...; or declare const tinymce: tinymce.EditorManager & typeof tinymce; |
Seems like there is already at least one precedent where the type annotation doesn't exactly match the actual type: #18043 |
narrowing does not change the type.. it narrows the set of possible values for the type based on control flow. i do not think this is related to the issue at hand. |
It's a bit similar for in both cases we can say that the type from the annotation is substituted with a type assignable to it. Also type guards do the same thing. |
So I just stumbled across this issue while refactoring type-declarations for a module called So for Personally I'd write such a module like this: declare namespace inquirer {
namespace ui {
class Prompt { }
}
}
declare var inquirer: inquirer.Inquirer;
export = inquirer; But TypeScript is still throwing errors. Personally I don't really like the way the declarations of the inquirer-module are written currently. Cause of TypeScript's lack of merging-support classes are written as interfaces with |
Having the same problems with The javascript API idea is this: export = X3D;
declare const X3D: X3D;
declare interface X3D
{
(…): Promise<void>;
noConflict(): X3D;
getBrowser(…): X3DBrowser;
…
}
declare namespace X3D
{
class X3DBrowser
{ … }
…
} I had to make it work for me by fixing various errors and problems in the definitions. But member types in the interface instance cannot be used for type expressions. With a namespace instead, I am hitting the same Multiple ways could have worked but none of these are supported, right?
A working technique is the duplication of interface code into a namespace (replacing the interface instance). This doubles the maintenance effort. Now after hours of thinking, I noticed that in this special case a single namespace (plus a function) is sufficient to describe export = X3D;
type X3D = typeof X3D;
declare function X3D(…): Promise<void>;
declare namespace X3D
{
// interface functions
function noConflict(): X3D;
function getBrowser(…): X3DBrowser;
…
class X3DBrowser …
} If the exported |
I'd like to +1 the capacity to merge namespaces with constants, specifically with arrow functions. I use an ugly workaround in these cases. Sharing it, in case anyone needs it. declare function FunctionWithNamespace(..._: Parameters<ReturnType<typeof create_arrow_fun>>): ReturnType<ReturnType<typeof create_arrow_fun>>;
(FunctionWithNamespace as any) = create_arrow_fun();
namespace FunctionWithNamespace {
...
} Put the constant as a function with |
But then if Looks like 7 years ago there were discussions of how should the declarations influence the type or the variable. |
I wrote this in closed #13536 first, but thought it might get lost there, so filing a new issue.
Merging
const
s with namespaces really makes sense. For a real-world example, let's take a popular library: TinyMCE, writing proper type definitions for which requires this feature. Namespaces are really convenient in this case because all the classes from the API are attached to thetinymce
namespace object or to its subnamespaces. In the API, there are normal classes liketinymce.Editor
and so called 'static classes' liketinymce.EditorManager
which are just a type (interface) plus an object value of this type attached to the namespace:Nothing unusual so far, but there is a plot twist. The namespace object
tinymce
itself implements thetinymce.EditorManager
interface. It could be easily and beautifully solved by merging aconst
with the namespace:But unfortunately this isn't allowed. The error message is:
Cannot redeclare block-scoped variable 'tinymce'.
The text was updated successfully, but these errors were encountered: