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

Enum export not working across multiple projects #4800

Closed
christyharagan opened this issue Sep 15, 2015 · 5 comments
Closed

Enum export not working across multiple projects #4800

christyharagan opened this issue Sep 15, 2015 · 5 comments
Labels
Bug A bug in TypeScript Won't Fix The severity and priority of this issue do not warrant the time or complexity needed to fix it

Comments

@christyharagan
Copy link

The error relates to enums, and exports using the new typescript node resolution (with the typings property in the package.json). I have tested this on typescript@next.

The bug can be reproduced through the following scenario: (please go to https://github.com/christyharagan/typeScript-enum-export-bug to find this code):

Three projects: a, b, c.

b depends on a
c depends on b

a exports an enum through its index.ts:

export enum E{}

b then exports a function that returns E through its index.ts:

import {E} from 'a'
export function f():E {
  return null
}

c then consumes f through its index.ts:

import {E} from 'a'
import {f} from 'b'

let e:E = f()

There is now an error for e:

Type 'E' is not assignable to type 'E'.

All three packages have a package.json that looks like this:

{
  "name": "b",
  "version": "1",
  "main": "lib/index.js",
  "typings": "lib/index.d.ts",
  "dependencies": {
    "a": "1"
  }
}

And a tsconfig.json that looks like:

{
    "compilerOptions": {
        "declaration": true,
        "module": "commonjs",
        "rootDir": "./src",
        "target": "es5",
        "outDir": "./lib"
    },
    "files": [
        "src/index.ts"
    ]
}

Furthermore, this defect occurs if f were to export another symbol (e.g. an interface) which references an exported enum somewhere within it's structure or hierarchy.

This only seems to affect enums, not other types.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 15, 2015

The problem is a/index.ts is loaded twice from two places, node_modules\a and node_modules\b\node_modules\a, and from the compiler perspective they are two different modules.

Enums are not checked structurally, each any two enum types are not assignable to each other, regardless of their shape; other structural checks would work, e.g. passing an interface with he same shape as the expected target type. A class with a private member, however, will behave like an enum, as a private has to originate from the same declaration, and as mentioned above, they are not.

Solutions, npm dedupe should solve this issue, assuming the version of the packages is compatible. the other possible solution would be implementing the suggestion in #4665 (comment).

The typescript resolver should attempt to dedupe packages in similar setup, so marking it as a bug.

@mhegazy
Copy link
Contributor

mhegazy commented Dec 1, 2015

After discussion this some more, 1. npm v3 and later should flatten by default, so no additional work needed by the compiler, and 2. enums should not be compared nominally, see #5740

@mhegazy mhegazy closed this as completed Dec 1, 2015
@mhegazy mhegazy added the Won't Fix The severity and priority of this issue do not warrant the time or complexity needed to fix it label Dec 1, 2015
@xogeny
Copy link

xogeny commented Dec 31, 2015

I don't understand, what is the resolution here? I am seeing the same issue. I simply want to define an enum in some dependency and then use it across projects. Your argument seems to be that an enum cannot be exported as a type (because possible values are not also exported?) and, therefore, two references to the same enum "type" via different paths are not considered equivalent types?

I think I understand the semantic challenge here. But in practical terms, it seems like this makes an enum completely useless (at least in the context of reusable, modular code). If the enum cannot be exported then it can only be referenced internally within that module (i.e., it must be treated as effectively private to that module). Is my understanding correct? Is this really the final word on the enum type? If so, I'll need to switch all my enums to primitive types...which would be a real shame and a real loss for type safety. Or am I missing something?

@mhegazy
Copy link
Contributor

mhegazy commented Jan 4, 2016

@xogeny this should be fixed in #6036

@xogeny
Copy link

xogeny commented Jan 4, 2016

Great. Thanks. 👏

I think I've already picked this up in typescript@next since I haven't seen this issue there.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Won't Fix The severity and priority of this issue do not warrant the time or complexity needed to fix it
Projects
None yet
Development

No branches or pull requests

4 participants