Skip to content
This repository has been archived by the owner on Jan 26, 2019. It is now read-only.

Const Enum undefined when imported from remote npm package in create-react-app project #356

Open
stephenkiers opened this issue Jul 4, 2018 · 7 comments

Comments

@stephenkiers
Copy link

Is this a bug report?

Yes

Can you also reproduce the problem with npm 4.x?

Yes

Which terms did you search for in User Guide?

enum, npm, import

Environment

here is the yarn.lock info
react-scripts-ts@^2.16.0:
  version "2.16.0"
  resolved "https://registry.yarnpkg.com/react-scripts-ts/-/react-scripts-ts-2.16.0.tgz#45f831a12139c3b59d6bb729c1b6ef51e0f22908"
  dependencies:
    autoprefixer "7.1.6"
    babel-jest "^22.1.0"
    babel-loader "^7.1.2"
    babel-preset-react-app "^3.1.1"
    case-sensitive-paths-webpack-plugin "2.1.1"
    chalk "1.1.3"
    css-loader "0.28.7"
    dotenv "4.0.0"
    dotenv-expand "4.2.0"
    extract-text-webpack-plugin "3.0.2"
    file-loader "0.11.2"
    fork-ts-checker-webpack-plugin "^0.2.8"
    fs-extra "3.0.1"
    html-webpack-plugin "2.29.0"
    jest "22.4.2"
    object-assign "4.1.1"
    postcss-flexbugs-fixes "3.2.0"
    postcss-loader "2.0.8"
    promise "8.0.1"
    raf "3.4.0"
    react-dev-utils "^5.0.1"
    resolve "1.6.0"
    source-map-loader "^0.2.1"
    style-loader "0.19.0"
    sw-precache-webpack-plugin "0.11.4"
    ts-jest "22.0.1"
    ts-loader "^2.3.7"
    tsconfig-paths-webpack-plugin "^2.0.0"
    tslint "^5.7.0"
    tslint-config-prettier "^1.10.0"
    tslint-react "^3.2.0"
    uglifyjs-webpack-plugin "^1.1.8"
    url-loader "0.6.2"
    webpack "3.8.1"
    webpack-dev-server "2.9.4"
    webpack-manifest-plugin "1.3.2"
    whatwg-fetch "2.0.3"
  optionalDependencies:
    fsevents "^1.1.3"
node -v

v10.5.0

yarn --version

1.7.0

Then, specify:

  1. Operating system: OSX
  2. Browser and version: na

Steps to Reproduce

See attached github repro that is minimal reproduction

https://github.com/stephenkiers/TypescriptRepo1

Remote Package Code

export const enum TEST {
    MAJOR = "major",
    MINOR = "minor"
}

Target Package Code

type IFoo = {
    type: TEST.MINOR|TEST.MAJOR;
    name: string;
};
const foo: IFoo = {
    type: TEST.MINOR,
    name: "Full Name"
};
console.log(foo.type === TEST.MINOR ? foo.name : "World")

Expected Behavior

Target Package should print Full Name

Actual Behavior

TEST is undefined, so there is Uncaught TypeError: Cannot read property 'MINOR' of undefined

Reproducible Demo

@DorianGrey
Copy link
Collaborator

DorianGrey commented Jul 5, 2018

Ok - this one is a bit more complex to explain, yet it's pretty straight forward.
To illustrate the problem, I've adjusted the import code in app.tsx to this:

import * as Bla from "@test/redux/src/index";

console.warn(Bla);

What would you expect to be the output of this?

...

Answer - something like: /static/media/index.903f54a8.ts.
Why?
Because the pattern for ts files is (currently) only applied to code inside of the src directory.
Every file that does not match any of the other patterns is treated as an asset, i.e. file-loader will take care of it, and return a string containing the resulting file path.

See the config snippets:

{
test: /\.(ts|tsx)$/,
include: paths.appSrc,
use: [
{
loader: require.resolve('ts-loader'),
options: {
// disable type checker - we will use it in fork plugin
transpileOnly: true,
},
},
],
},

{
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},

Besides, I wouldn't recommend to use dev version of typescript (in your case, a dev version of 3.0) - they are too unstable for production usage, and in most cases don't provide all features scheduled for the particular version.

See the more details discussion / explanation here: #348

@stephenkiers
Copy link
Author

Thanks for you prompt, insightful response. The problem is similar to what I guessed it would be, and you were very helpful pointing out the relevant code.

For the record, the dev version of typescript was simply to rule out any issues within typescript; as I submitted this as a issue to the official typescript project as well.

I will look at #348 and see if we can come up with a solution on our side.

Really appreciate the feedback. 👍

@stephenkiers
Copy link
Author

Created a pull request that adds the ability to enable typescript processing for a node_modules folder. Please take a look, #358

@larrybotha
Copy link

Was experiencing this, too. From #348 (comment) I added the package to the webpack configs' includes (project is ejected):

  // Compile .tsx?
  {
    test: /\.(ts|tsx)$/,
    include: [ paths.appSrc, path.resolve('..', 'node_modules', '<package-name>') ],
    use: [
      {
        loader: require.resolve('ts-loader'),

enums are now doing that thang that they're s'posed to.

@stephenkiers
Copy link
Author

This is exactly what my pr did. However, because this is such a niche issue, we decided to fork instead of merging into master.

@alouiseq
Copy link

@larrybotha @stephenkiers I'm encountering the same issue. Will you be submitting a PR to simply add the external lib to the include path? It seems like a reasonable add on to the config.

@WorldMaker
Copy link

How is this is a niche issue? All of @types is imported from node_modules, for one thing, and that's a lot of opportunity for errors of this sort.

I've got several libraries I use regularly that I'd rather import the TS sources directly from node_modules, and get TS' transpilation behavior for free (as opposed to needing a separate Babel pass and/or requiring additional polyfills), I've got TS-only npm packages that only include TS source. One easy example here is that using @reactivex/rx-ts or especially @reactivex/ix-ts allows you to set your target lib once in your root config, and not have to also "declare" it in a specific npm package dependency such as @reactivex/ix-es2015-esm. (I say especially for Ix here, because getting the right combination of asynchronous for generator support is much easier if you let TS handle it top-to-bottom.)

It was a shock to find an import resolving to /static/media/name.hash.ts just now. That's definitely not behavior I would expect. I was hoping not to need to eject this soon on this project.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants