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

const enum inside a namespace makes it treated as a value #17372

Open
ghost opened this issue Jul 24, 2017 · 5 comments
Open

const enum inside a namespace makes it treated as a value #17372

ghost opened this issue Jul 24, 2017 · 5 comments
Labels
Bug A bug in TypeScript
Milestone

Comments

@ghost
Copy link

ghost commented Jul 24, 2017

TypeScript Version: nightly (2.5.0-dev.20170719)

Code

declare const N: number;
declare namespace N {
    const enum E {}
}

Expected behavior:

No error. N does not contain any values, so it should be OK to merge it with a value.

Actual behavior:

src/foo.d.ts(1,15): error TS2451: Cannot redeclare block-scoped variable 'N'.
src/foo.d.ts(2,19): error TS2451: Cannot redeclare block-scoped variable 'N'.
@RyanCavanaugh
Copy link
Member

We'll still need to block this under --preserveConstEnums

@weswigham
Copy link
Member

weswigham commented Jul 24, 2017

More generally, then, we believe

const enum Foo {A, B}
declare const Foo: number;

Is allowable?

I think I understand why this isn't actually a bug - I think it's intended behavior: A const enum is a value-meaning symbol, as it is usable in value positions (even if they're replaced at compile time). As such, a namespace containing it must be valid in value positions and so on; and another value declaration cannot exist for the same symbol (or any symbol in that value-meaning chain) unless they are mergable.

@weswigham
Copy link
Member

Pretty much the same with #16804, which is a variation on the same issue.

@UselessPickles
Copy link

UselessPickles commented Nov 22, 2017

I just ran into this issue today. Here's my vote for "I think this is a bug that should be fixed", although I see the complication.

At compile time, a const enum's value is a "value-meaning symbol" that needs to follow all the same rules as other "value-meaning symbols", but at runtime the enum (and its values) doesn't exist at all.

Seems like a special edge case that, when not using --preserveConstEnums, a const enum's value should not be considered a "value" for the purpose of determining whether a namespace "contains values". But for all other purposes, a const enum's value should still be treated like a "value-meaning symbol".

@jeswin
Copy link

jeswin commented Aug 20, 2021

I believe I'm facing the same issue here; I just wanted to add another example.

export function createElement() {
  // some implementation...
}

export const h = createElement;

// This works
export namespace createElement {
  export import JSX = JSXTypes;
}

// This does not work.
export declare namespace h {
  export import JSX = JSXTypes;
}

The reason this is needed is because JSX namespace is picked up from createElement (or h) when jsxFactory = "createElement" (or "h").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

No branches or pull requests

5 participants