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

Allow emitDeclaration and isolatedModules together #29490

Closed
5 tasks done
SimenB opened this issue Jan 19, 2019 · 19 comments · Fixed by #33380
Closed
5 tasks done

Allow emitDeclaration and isolatedModules together #29490

SimenB opened this issue Jan 19, 2019 · 19 comments · Fixed by #33380
Assignees
Labels
Committed The team has roadmapped this issue Fix Available A PR has been opened for this issue Suggestion An idea for TypeScript

Comments

@SimenB
Copy link

SimenB commented Jan 19, 2019

Search Terms

isolated modules emit declaration

Suggestion

In the blog post introducing Babel 7, it's recommended to use --isolatedModules in the "Caveats" section (https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/).

We use Babel to transpile our TS to better work with other tools in the ecosystem (such as Emotion or Jest), but we'd also still like to generate declaration files so consumers of our libraries can enjoy the type information.

However, when trying to follow the advice of adding isolatedModules to our config, we get the following warning:

tsconfig.json:5:5 - error TS5053: Option 'declaration' cannot be specified with option 'isolatedModules'.

5     "declaration": true,
      ~~~~~~~~~~~~~

Use Cases

As mentioned, I'd like to create declaration files for libraries who are transpiled using babel. I'd also like to make sure that whatever guarantees isolatedModules adds to allowed syntax are present, outside of the type information.

Babel itself will complain if we use e.g. const enum, but that only happens at compile time - isolatedModules will also show a warning in the IDE while writing the code.

Examples

Same as we currently get with {"declaration": true, "emitDeclarationOnly": true}, but with added {"isolatedModules": true}.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@dlannoye
Copy link
Member

I am also looking for something similar. I will be using babel as a compiler via webpack for a monorepo, but still want features like project references for the editor experience in my monorepo and generating d.ts files for packages that are published.

For my situation having a way to enforce the same limitations on language features that aren't supported by isolated modules without the restrictions on other typescript features would be ideal. I think that just means having an alternative way of treating usage of const enum, namespace, and re-exporting types by name as errors.

@weswigham weswigham added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. labels Jan 23, 2019
@mheiber
Copy link
Contributor

mheiber commented Feb 28, 2019

Why does this restriction currently exist?
Related StackOverflow question asking about the restriction: https://stackoverflow.com/questions/49403410/why-declaration-can-not-be-used-together-with-isolatedmodules-in-typescript

@RyanCavanaugh RyanCavanaugh self-assigned this Feb 28, 2019
@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Feb 28, 2019

Everyone in the room is currently trying to figure out why this is a restriction. 😅

@mheiber
Copy link
Contributor

mheiber commented Mar 7, 2019

It looks like the restriction was there since the branch for separate-compilation (now isolatedModules) was first merged into master.

The restriction was added (I think) in response to feedback which pointed out that declaration: true makes no sense for transpile (now transpileModule).

Maybe the same restrictions need not apply for isolatedModules and transpileModule, since allowing emit of declaration files makes sense for the former but not the latter.

@RyanCavanaugh RyanCavanaugh added In Discussion Not yet reached consensus and removed Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. labels Mar 8, 2019
@mheiber
Copy link
Contributor

mheiber commented Mar 20, 2019

@RyanCavanaugh @SimenB proposed above allowing emitDeclaration and isolatedModules together. This issue is marked Needs Proposal.

What else is required in order for this to be a full-fledged proposal?

@weswigham
Copy link
Member

FYI, for anyone still reading this: The reason is for the same reason you can't use const enums in isolated modules: type information. Since isolated modules compiles each file individually without the types of the files it depends on, any inferred type we would write to a declaration file would potentially be incorrect, as their calculation would be missing information from the rest of the compilation. There is a limited subset of declaration emit where no types are inferred in the output which could be supported, however.

@mheiber
Copy link
Contributor

mheiber commented Mar 20, 2019

Thanks Wesley! I understand now.

What's recommended way for a user of babel-typescript to also generate declaration files? Something like the following?

  • Have a main tsconfig used for building and checking
  • Have another tsconfig for declarations that extends the first tsconfig and has the following overrides: {"isolatedModules": false, "emitDeclarationOnly": true}

@SimenB would that meet your needs as well?

@SimenB
Copy link
Author

SimenB commented Mar 20, 2019

I'd have to run tsc twice? Would that bust the cache of tsconfig.tsbuildinfo?

@weswigham
Copy link
Member

I'd have to run tsc twice? Would that bust the cache of tsconfig.tsbuildinfo?

You should be able to specify a separate tsbuildinfo path for each build so they don't mangle one another's incremental data.

@mheiber
Copy link
Contributor

mheiber commented Mar 20, 2019

@weswigham it doesn't seem like specifying the a separate tsbuildinfo path may not be necessary

I'm seeing that the name of the tsconfig is automatically used as part of the name of the tsbuildinfo file.

Given these tsconfigs:

tsconfig.json

{
    "compilerOptions": {
        "incremental": true,
        "isolatedModules": true
    }
}

tsconfig-for-declarations.json

{
    "extends": "./tsconfig",
    "compilerOptions": {
        "emitDeclarationOnly": true,
        "isolatedModules": false,
        "declaration": true
    }
}

When I run both tsc and tsc -p tsconfig-for-declarations.json I see two separate buildinfo files on disk:

  • tsconfig-for-declarations.buildinfo
  • tsconfig.buildinfo

tested on Version 3.4.0-dev.20190320

@mheiber
Copy link
Contributor

mheiber commented Apr 21, 2019

@weswigham , you said:

There is a limited subset of declaration emit where no types are inferred in the output which could be supported, however.

Would this be the same limited subset that applies to TS files? If so, it seems like the restrictions would be worth it. Would implementing this change be a big effort or a small tweak? I know some people who may be interested in implementing.

@mheiber
Copy link
Contributor

mheiber commented May 20, 2019

@weswigham checking in on this issue again.

We'd really like to get the extra checks from --isolatedModules while also generating declaration files. Doing an extra pass would really slow down our pipeline.

Is more information needed? Some question here. Thanks for your help with this issue.

@mheiber
Copy link
Contributor

mheiber commented Jun 6, 2019

Pinging about this again.
We'd be willing to make this change if it's of manageable size.

@DanielRosenwasser
Copy link
Member

@sheetalkamat is this small enough? Is it a matter of just disabling the check?

@DanielRosenwasser DanielRosenwasser added this to the TypeScript 3.6.0 milestone Jun 10, 2019
@DanielRosenwasser
Copy link
Member

P.S. I'm going to assign you but if the issue is scoped enough, I'm going to encourage @mheiber to send a PR.

@mheiber
Copy link
Contributor

mheiber commented Jul 29, 2019

@sheetalkamat , do you have guidance for us re:

  • level of effort needed for this fix
  • level of expertise needed for this fix

If both are low/medium, we might be able to find someone who can contribute a fix.

Thanks for your help.

@sheetalkamat
Copy link
Member

@mheiber @DanielRosenwasser and myself had discussion offline and it seems like the use case of what should be emitted in d.ts file is kind of vague. We are waiting on @RyanCavanaugh to be back to discuss this further to understand what .d.ts emit means, do we need to put some kind of restriction (eg specifying all types and nothing can be inferred) is still unclear. We also need to decide on what builder needs to do depending on outcome of .d.ts emit.

I am removing help wanted label from this as we are yet to come to conclusion on desired behavior.

mean while we would like to know why do you need to use isolatedModules is it for faster .js emit which checks only that file? What about --incremental flag with requiring you to compile only subset of files with each change.

@sheetalkamat sheetalkamat removed the Help Wanted You can do this label Jul 31, 2019
@mheiber
Copy link
Contributor

mheiber commented Aug 2, 2019

@sheetalkamat thanks for looking into this and asking about our use cases.

We're using isolatedModules because we want to be able to do separate compilation with ts.transpileModule in our Gulp pipeline. We use isolatedModules to verify that separate compilation is safe. Here are some of the specific reasons:

  • simpler
    • we can remove our dependency on the massive amount of plumbing between Gulp and the TS compiler API that is in gulp-typescript.
  • fast incremental builds and fast initial builds.

We are excited to take advantage of your work on incremental compilation, but can't use it yet because (as far as I know) the TS compiler API does not yet offer incremental compilation

  • memory usage: we're currently stalling our entire pipeline so that all the files in our build are synchronously available for the TS compiler API.
  • performance in general: we are considering running the checker in a separate process, or making type-checking optional
  • compatibility with all TS tooling:
    • we may use babel-plugin-typescript in future, which does separate compilation (and therefore needs to be checked with --isolatedModules).

cc @robpalme: I think Rob may have more thoughts on why we're interested in --isolatedModules.

@RyanCavanaugh RyanCavanaugh added By Design Deprecated - use "Working as Intended" or "Design Limitation" instead Committed The team has roadmapped this issue and removed In Discussion Not yet reached consensus By Design Deprecated - use "Working as Intended" or "Design Limitation" instead labels Aug 21, 2019
sheetalkamat added a commit that referenced this issue Sep 11, 2019
sheetalkamat added a commit that referenced this issue Sep 11, 2019
@sheetalkamat sheetalkamat added the Fix Available A PR has been opened for this issue label Sep 11, 2019
@mheiber
Copy link
Contributor

mheiber commented Oct 7, 2019

thanks @sheetalkamat and team!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Committed The team has roadmapped this issue Fix Available A PR has been opened for this issue Suggestion An idea for TypeScript
7 participants