wmonk / create-react-app-typescript

DEPRECATED: Create React apps using typescript with no build configuration.
3.7k stars 492 forks source link

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

Open stephenkiers opened 6 years ago

stephenkiers commented 6 years ago

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 commented 6 years ago

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: https://github.com/wmonk/create-react-app-typescript/blob/e4b1f9424fa14f7aae7f0cbf5fd64e18dd273527/packages/react-scripts/config/webpack.config.dev.js#L173-L185

https://github.com/wmonk/create-react-app-typescript/blob/e4b1f9424fa14f7aae7f0cbf5fd64e18dd273527/packages/react-scripts/config/webpack.config.dev.js#L228-L238

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: https://github.com/wmonk/create-react-app-typescript/issues/348

stephenkiers commented 6 years ago

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 commented 6 years ago

Created a pull request that adds the ability to enable typescript processing for a node_modules folder. Please take a look, https://github.com/wmonk/create-react-app-typescript/pull/358

larrybotha commented 6 years ago

Was experiencing this, too. From https://github.com/wmonk/create-react-app-typescript/issues/348#issuecomment-401583230 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 commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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.