Skip to content

Conversation

@strothj
Copy link

@strothj strothj commented Sep 5, 2018

Fixes #295.

I changed the type definition for Level to use a naked enum. This makes the type definitions compatible with Babel compiled TypeScript.

I enabled the isolatedModules compiler flag so that the introduction of incompatible code will be caught as an error.

const enum, if I'm not mistaken, only controls emit behavior. Changing it to a normal enum in the type definitions should not change the semantic meaning.

@sindresorhus
Copy link
Member

const enum is a commonly used language feature. We're not going to change just because Babel doesn't fully support TS. It's up to Babel to support the TS ecosystem, not the other way around.

@sindresorhus
Copy link
Member

You should open an issue on Babel instead.

@strothj
Copy link
Author

strothj commented Sep 5, 2018

Sure, no problem. Thank you for your time.

@chicoxyzzy
Copy link

Actually it's not Babel issue. It's more like TypeScript issue with isolated modules.

@strothj strothj deleted the patch-1 branch September 8, 2018 16:33
@alangpierce
Copy link

Please reconsider this PR. This isn't a Babel issue; const enum is fundamentally incompatible with any TS compilation strategy that operates on each file independently, and TypeScript explicitly exposes an --isolatedModules option so that projects can compile with this strategy. Compiling files independently improves build performance significantly, and I do it for all of my TS projects (and I don't use Babel). In addition to Babel, here are some other situations where isolatedModules is necessary:

Independently, using const enum in published packaged definitions can cause subtle bugs because it means the constants will be inlined at compilation time. That means that any updates to the enum won't be picked up when upgrading chalk because the old values will still be inlined.

Here are some comments from TypeScript team members saying that you should never use const enums in published type definitions: DefinitelyTyped/DefinitelyTyped#23002 (comment) , microsoft/TypeScript#20703 (comment) . It's fine to use them internally within a project, but across projects, it's fragile and breaks isolatedModules users.

My current situation is I have a large TypeScript project and recently added chalk as a dependency and it broke my build because I use isolatedModules. Chalk is great, but I'm not willing to slow down my build just to use it, so I removed isolatedModules and have my build system configured to transpile files individually anyway. This works and keeps the build fast, but is unsettling because it means any use of const enums (including Level) will typecheck but crash at runtime, so I really would like to add isolatedModules back to my TS config. I get that it's annoying to not have access to the const enum feature in exported definitions, but avoiding it is much more ecosystem-friendly.

Note that this PR is incomplete. To change const enum to enum in the .d.ts file, you'll need to define something equivalent to the enum in the source JS. Otherwise, code like Level.Ansi256 will crash at runtime since Level doesn't exist (I think). I think the easiest way to do this is to just define a JS object that looks like the enum.

@the-simian
Copy link

the-simian commented Mar 18, 2019

There appears to be some discussion on this here: microsoft/TypeScript#20703

Kind of a bummer, but I'm using create-react-app which (if you don't eject) heavy-handedly forces isolatedModules to true. I ejected for months and months, but I'm trying to leverage the benefits of not ejecting at this time. That means that the only workaround I have, as I am beholden to chalk for a 3rd party dependency, is to set skipLibCheck to true in the tsconfig.json. This works, with the obvious downsides.

@alangpierce
Copy link

@the-simian I submitted microsoft/TypeScript#28465 and I think (but haven't confirmed) that it will be released in TypeScript 3.4, coming out very soon. That means that after upgrading TypeScript, you'll only get errors if you try to use Level enum, not by simply including chalk as a dependency.

(For other reasons mentioned above, I still think it's best for libraries to either ship concrete (non-const) enums or use a union type instead.)

michaelsbradleyjr added a commit to embarklabs/embark that referenced this pull request May 2, 2019
The more recent version of TypeScript works around a [problem][chalk-problem]
encountered with the chalk package's type definitions.

[chalk-problem]: chalk/chalk#296 (comment)
michaelsbradleyjr added a commit to embarklabs/embark that referenced this pull request May 3, 2019
The more recent version of TypeScript works around a [problem][chalk-problem]
encountered with the chalk package's type definitions.

[chalk-problem]: chalk/chalk#296 (comment)
@Macil
Copy link

Macil commented Jan 29, 2020

@alangpierce On Typescript 3.7.5, I get this error just from import 'chalk' without using anything from it:

node_modules/chalk/index.d.ts:403:16 - error TS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.

403  Level: typeof LevelEnum;
                   ~~~~~~~~~


Found 1 error.

I wonder if that change to typescript was not enough, or if the issue was re-introduced in either typescript or by some change in this library since then.

@strothj
Copy link
Author

strothj commented Jan 29, 2020

@alangpierce On Typescript 3.7.5, I get this error just from import 'chalk' without using anything from it:

node_modules/chalk/index.d.ts:403:16 - error TS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.

403  Level: typeof LevelEnum;
                   ~~~~~~~~~


Found 1 error.

I wonder if that change to typescript was not enough, or if the issue was re-introduced in either typescript or by some change in this library since then.

That error is caused by the fact that you have the compilerOption isolatedModules set to true. This is normally set to true when using something like Babel to compile your code. isolatedModules means that each module needs to be able to be compiled in isolation. The const enum cannot.

You can add "skipLibCheck": true, to your compilerOptions to disable type checking of type declarations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeScript error when using --isolatedModules

6 participants