Parcel: Use @babel/preset-typescript to transform TS files

Created on 17 Sep 2018  ยท  21Comments  ยท  Source: parcel-bundler/parcel

Thanks for parcel :package: :tada: it has been working great!

๐Ÿ™‹ feature request

Now that Parcel has Babel 7 support (:tada:), it would be great if parcel would use @babel/preset-typescript in order to remove the Typescript type annotations rather than using tsc.

Why
It would be simpler to have the code being processed _just_ by babel, rather than by typescript _and_ babel. I also imagine it would be faster because it means less parsing/stringifying

๐Ÿค” Expected Behavior

  • Disable TSC if @babel/preset-typescript is in user's config
  • Otherwise, use TSC

๐Ÿ˜ฏ Current Behavior

I believe currently all .ts files are being processed by tsc, and the resulting code is passed to babel, which applies any additional transformations.

๐Ÿ”ฆ Context

I would rather stick to all-babel for transformation rather than tsc and babel. This isn't a huge deal, but I imagine it would help with performance.

Feature TypeScript babel โœจ Parcel 2

Most helpful comment

This is implemented in Parcel 2 as the default TypeScript transform. A separate plugin @parcel/transformer-typescript-tsc is available for those that want to use TSC instead.

All 21 comments

I think babel's typescript support does not support all language features though. See the caveats listed here: https://babeljs.io/docs/en/next/babel-plugin-transform-typescript.html#caveats. I think it might be problematic to switch to babel by default for those issues... Thoughts?

I don't think it would be problematic if a user has @babel/preset-typescript in their babel config. This means that the user is opting-in to this feature. Basically what this comes down to is Parcel disabling tsc when users have @babel/preset-typescript.

I see. So default behavior would still be to use tsc for typescript files.

I should also note that we may want to bring actual type checking support to core like parcel-plugin-typescript has rather than just compilation. So that's yet another mode.

Hmm, that makes things more complicated :joy:.

I know that other people have other opinions, but my opinion is that:

  • Static analysis/checking tools (TS type-checking, eslint, tslint, etc.) should run in the editor, and in CI
  • Build tools should complete regardless of TS type status, eslint status, tslint status, etc.

I feel like checking for @babel/preset-typescript in babel config would accomplish this, because users who opt in to this would be disabling the TS type-checking support (including within parcel if that gets added).

Is there a scenario where a user would want to use @babel/preset-typescript _and_ tsc for type-checking?

My personal preference would be to have full type-checking always going on to catch any knock-on changes from extended exports or inferences (e.g. one type change breaks a file 3 imports away) before commits happen. With that said, it would make sense to use tsc to run (only) type checking in a separate process from Babel in this case.

@icopp if the Babel compilation completed before the type checking, would you expect parcel to wait for the type checking to complete before writing the compiled files to the fs? Or would the Babel compilation write to the fs regardless of whether the TS types had errors?

My experience trying to switch a medium sized codebase to babel-typescript last week was that babel-typescript does not generate equivalent code to tsc + babel, and introduced a number of regressions. I would let it bake a bit longer before trying to use it as the default for most users in a zero-config tool like Parcel.

Edit: this is actually why I'm trying Parcel now on the same project, I'd rather not spend my time figuring out these incompatibilities.

Regardless, if a user has @babel/preset-typescript in their babelrc, it would make sense to disable the tsc transformation, no?

Sorry I missed that in the original PR. Making it "opt in" at least wouldn't bother me.

If I were to use that mode, I would be fine with writing/serving compiled JS before type checking completes, but definitely would expect the tool to wait for type checking and exit with an error code when it's not watching for file changes.

@devongovett would you accept a PR that implements this behavior?

Hey, just chiming in here with my 2 cents.

A good reference implementation for TypeScript + Babel would be on Microsoft/TypeScript-Babel-Starter. The ideal setup would be to let Parcel handle the transpilation with babel, and then have TypeScript typechecking by running tsc with the --noEmit flag separately.

Regarding the unsupported features mentioned here, most of them, like namespaces and export =/import = syntax, are legacy features that aren't used anymore in favour of ES-style modules/imports. And IIRC, if you do use them, TypeScript will return type errors if you enable isolatedModules in your tsconfig.json.

This is blocking us from moving from Webpack to Parcel. We use Typescript and Emotion. Emotion needs a custom babel plugin to take full advantage of it. So we build with Babel only using the typescript babel preset to avoid using two compilers and slowing down builds. We use tsc only as a linter like eslint and flow are used.

The caveats in using the typescript preset are not really relevant when writing modern Typescript.

@resir014

Regarding the unsupported features mentioned here, most of them, like namespaces and export =/import = syntax, are legacy features that aren't used anymore

@epeli

The caveats in using the typescript preset are not really relevant when writing modern Typescript.

I feel compelled to point out that @babel/preset-typescript _also_ misses certain modern features. (For example the PR to support optional elements in tuple types, a feature added in 3.0, is here: https://github.com/babel/babel/pull/8720)

Static class members and dynamic imports require adding @babel/plugin-proposal-class-properties and @babel/plugin-syntax-dynamic-import respectively.

The final thing that doesn't (and can't) work is type re-exports (e.g. export {SomeType} from './another-module'). Compiling this correctly requires type information about another-module to see that SomeType doesn't refer to a value. To work around this one must write: import {SomeType} from './another-module'; export type SomeType = SomeType.

None of these are show stoppers, and I'm still :+1: on the proposal. I also think that Parcel could make an effort to avoid these traps and/or warn users about sub-optimal babel configurations.

I don't think we should be changing the typescript implementation anytime soon. Definitely not before Parcel 2. This would be a breaking change anyways, as babel TS is lacking various features of TS.

It will be configurable in Parcel 2 anyways, not sure what we should default to though. Babel TS would be easier to implement and possibly be faster as we can re-use the AST.

This is still proposing using tsc everywhere _except_ when Babel preset typescript is enabled. I don't see a use case where a user would have Babel preset typescript and would still want to use tsc

I don't think this is breaking enough to require waiting until parcel 2. This only affects users with Babel preset typescript in their babelrc

Ow thought it said replace, should have re-read the thread. Yeah this isn't a breaking change in that case.

It seems that transpiling with Babel and separately checking types with tsc has become the encouraged practice in TypeScript land, or so I infer from the setup and documentation of Microsoft's official project starter.

Is there a way to do that in Parcel?

@bard made me think that other people could need it, so if anyone else want a way to use Babel instead of TSC in parcel right now.
https://github.com/Banou26/parcel-plugin-babel-typescript
Could be of help.

This is implemented in Parcel 2 as the default TypeScript transform. A separate plugin @parcel/transformer-typescript-tsc is available for those that want to use TSC instead.

This can be closed now, no ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dotdash picture dotdash  ยท  3Comments

davidnagli picture davidnagli  ยท  3Comments

davidnagli picture davidnagli  ยท  3Comments

Niggler picture Niggler  ยท  3Comments

termhn picture termhn  ยท  3Comments