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

Feature Request: Typescript support #3

Closed
trevor-atlas opened this issue Dec 5, 2017 · 34 comments
Closed

Feature Request: Typescript support #3

trevor-atlas opened this issue Dec 5, 2017 · 34 comments

Comments

@trevor-atlas
Copy link

No description provided.

@morajabi
Copy link

morajabi commented Dec 5, 2017

@devongovett If you had some time, can you please write the steps needed/files to be changed to enable TS support. Then I can try to do so too. Thanks 😉

@sylvainpolletvillard
Copy link

sylvainpolletvillard commented Dec 6, 2017

Since parcel already has babel support, you can try using babel-preset-typescript , currently in beta. Register the .ts extension here and configure .babelrc to use the typescript preset.

@wyqydsyq
Copy link

wyqydsyq commented Dec 6, 2017

Unfortunately babel-preset-typescript isn't particularly useful in most cases as it only does a transform and doesn't actually compile using tsc, so you'll never get any type checking (the main reason to use TypeScript) with it, just es5 output.

It seems the ideal solution to this issue would be for Parcel to support TypeScript natively as an opinionated decision like fusebox does, or for someone to implement a TypeScript plugin that passes .ts / .tsx files through tsc prior to the Babel step (so you still get your Babel polyfills etc. after tsc has converted your TS to ES2015).

Personally I would prefer the former as I think it would be much cleaner to use and I feel the vast majority of the JavaScript community is already using TypeScript so this would be a desirable feature for a huge portion of your userbase.

@devongovett
Copy link
Member

devongovett commented Dec 6, 2017

I think TypeScript support should totally be built in. We may require that you install typescript in your project so we don't depend on it unnecessarily similar to how we do it for stylus, sass, etc. But you shouldn't need to install an additional plugin beyond this.

I don't personally have any experience with typescript, so I'll need some input here. I like the idea of using babel-preset-typescript if that works, since other babel plugins will work along side without needing to have typescript codegen and parse again with babel. Open questions:

  • Does babel-preset-typescript actually work as typescript users expect?
  • I guess you wouldn't get type checking with babel-preset-typescript - but doesn't that require cross-file analysis anyway in case you import types? Because of Parcel's parallel architecture, this will be harder to do. So I guess the question is whether this is ok? Should Parcel do type checking, or should it work more like a linter (separate task)?

@wyqydsyq
Copy link

wyqydsyq commented Dec 6, 2017

Yeah I agree, having it as a peer-dependency would be ideal so that the typescript version you use isn't tightly coupled to your parcel version.

tsc provides a lot more than type checking, I just mentioned that as it's the primary feature. Using the babel preset would mean you miss out on all warnings from tsc, for example code quality compiler options like allowUnreachableCode, noImplicitAny and so on would not be enforced. Generally developers would see these warnings in their editor, but I don't think that is something to be relied on.

Workflows for bundling a TypeScript project via Browserify, Webpack or FuseBox all utilize tsc and will output errors / abort build if there are any tsc warnings, I believe a lot of developers have relied on this in their CI (so their CI build fails if there's any TS warnings). A lot of people using stuff like webpack-dev-server are using it instead of tsc -w and so expect to see any warnings come up in their terminal / browser.

From what I can see the babel preset is basically just stripping all the TS stuff so you get plain JavaScript, going by this another potential solution could be to use the babel preset for transpiling, but call tsc --noEmit (which will output any warnings and return an error exit code if there are any problems while never actually outputting any files) before the Babel step on projects that have a tsconfig.json or typescript in their package.json. This would allow Parcel to transpile TS → JS using just the Babel plugin, while still aborting and providing warnings to TypeScript users if something is wrong.

ts-node used a similar mechanism; they do a basic transpile (via TypeScript's transpileModule rather than a Babel plugin), and does the TypeScript type checking as a separate process: TypeStrong/ts-node#44

@lastmjs
Copy link

lastmjs commented Dec 6, 2017

Some suggestions. I think it would be ideal to send TypeScript errors/warnings to the browser console instead of to the local machine console. Really, TypeScript errors are just type check warnings, and it feels like a more unified experience to have all of my client code errors and warnings appear in one place, the browser console. It would also be ideal to not force the compilation to fail if there are any TypeScript errors, because again, they aren't really errors, the code will often still run, and for development it is sometimes nice to ignore TypeScript warnings to move quickly and prototype, going back to put in the types after things settle a bit. Allowing these two options would be ideal, and if you need help I've got som experience implementing this in a similar project.

@GeeWee
Copy link

GeeWee commented Dec 6, 2017

Worth noting is that Babel 7 will come with built in typescript support, so the problem might solve itself in the near future

@sylvainpolletvillard
Copy link

sylvainpolletvillard commented Dec 6, 2017

@wyqydsyq VSCode, Webstorm and probably other editors support TypeScript language service for code validation and type-checking errors directly inside the editor. This means you can have a nice Typescript developer experience while improving the compiler performance, because as you said, Babel does not do any type-checking. I remember I saw some tweets about using Babel instead of tsc to improve build time. I need to check my sources and find some benchmarks though.

edit: here's the tweet I read https://twitter.com/jaredpalmer/status/936249988270706688

@Olian04
Copy link

Olian04 commented Dec 6, 2017

@GeeWee in planning for Babel 7

You can now use babel-preset-typescript to allow Babel to strip types

Wouldn't this bypass the type checking of tsc?

@jamiebuilds
Copy link
Member

I think we should do both:

  • Using babel-preset-typescript should just work
  • There should be a way to run the tsc compiler

There's no way to guarantee that Babel and TypeScript are perfectly in sync with syntax support. So people should have the option to stick to the TypeScript compiler.

@gargantuan
Copy link

I'd suggest stating with Babel, and putting tsc on the backlog.

@jamiebuilds
Copy link
Member

In the interest of keeping the noise down on this issue, please use the 👍 button on the original post or any comments.

@parcel-bundler parcel-bundler deleted a comment Dec 6, 2017
@GeeWee
Copy link

GeeWee commented Dec 6, 2017

@Olian04 yeah that's a good point, we'd want to fork and typecheck in a separate process, like e.g. ts-loader does, but in general not having the typechecker run 24/7 is not as big of a problem as one night think as the editors will autocomplete fine without.

@steadicat
Copy link

It’s worth keeping in mind that, even if you don’t care about type-checking,tsc is still a very different compiler than Babel. Case in point, there was recently an article bemoaning the output of a Babel for..of loop. tsc doesn’t have this problem.

On top of that, Babel 7 still doesn’t support some tsc features (namespaces and const enums come to mind). Arguably there will always be mismatches, especially since TypeScript moves pretty fast.

Finally, tsc is quite configurable, with many compiler options which are not type-related, but change the behavior or output of the compiler. Unless Babel supports all of these, switching a TypeScript codebase to a Babel-powered Parcel will break things, which will reflect poorly on Parcel, IMO.

Performance-wise, according to a Twitter thread linked here earlier, tsc in transpileOnly-mode is pretty much as fast as Babel. I never had issues with tsc performance.

@lastmjs
Copy link

lastmjs commented Dec 6, 2017

Also, in my experience the TypeScript compiler has been very nice to work with as an embedded library.

@wyqydsyq
Copy link

wyqydsyq commented Dec 7, 2017

Interestingly the first issue ever in TypeStrong's discussions repo is about normalizing non-standard tsc compiler options from different libraries, if the transpileOnly option from ts-loader mentioned there were to be adapted as a standard option, Parcel could run tsc --transpileOnly and tsc --noEmit in separate threads to get both fast transpilation and TypeScript warning feedback without having to implement anything bespoke

@devongovett
Copy link
Member

Cool, sounds like we should go with the regular TypeScript compiler for compatibility by default. I think we can start with transpileModule for now to unblock people quickly, and maybe add type checking later.

One unfortunate thing about this vs using babel is that it will probably require multiple parses/codegens, which I was trying to avoid for performance. We don't really want to reimplement all of the dependency analysis and other things that are currently implemented on top of the babel AST though. That means that TypeScript will parse and compile, and then babel will do the same. This isn't any worse that other bundlers currently, but a pure babel pipeline would avoid that.

Anyway, here's how someone might go about doing this:

You'll need to add a new Asset type. I'd inherit from JSAsset so you get the rest of the analysis for free. Basically you need to wrap the parse function so it calls typescript first.

Here's some pseudocode.

const Asset = require('../Asset');
const localRequire = require('../utils/localRequire');

class TypescriptAsset extends JSAsset {
  async parse(code) {
    // require typescript, installed locally in the app
    let typescript = localRequire('typescript', this.name);

    // call typescript compiler
    super(transpileModule(code));
  }
}

Would someone like to take this on? 😉

@parcel-bundler parcel-bundler deleted a comment from sanketsahu Dec 7, 2017
@jamiebuilds
Copy link
Member

@d4rkr00t Maybe you want to take this on? 😉

@d4rkr00t
Copy link

d4rkr00t commented Dec 7, 2017

I would love to, but seems like it's a little bit too late :)

@devongovett
Copy link
Member

#84 has been merged and released in v1.1.0, which should cover the basics of transpiling. Closing this issue. If someone wants to open another one for typechecking support, feel free.

@jraoult
Copy link

jraoult commented Dec 8, 2017

EDIT: Ignore me, I was testing the wrong version. 1.1.0 is not in NPM yet.

@devongovett I know this issue is already closed but I just found a bug. If the script index file has a .ts extension, the mime module, (transitive dependency of serveStatic) will interpret it as a "video/mp2t" (cf https://raw.githubusercontent.com/broofa/node-mime/master/types/standard.json).

My intuition is that the transpiled file should not have the .ts extension anyway since it is not typescript at this stage anymore but we could also override the default mime type to map ts to application/javascript content type.

@mihailik
Copy link

TypeScript has neat and not-complex tsconfig.json for driving/tweaking compilation. Ideally that's supported automatically out of the box.

TypeScript without tsconfig.json by default just bulds every .ts file it can find in directory/subdirectory with reasonable default settings.

That's what should be the baseline default expectation.

@DeMoorJasper
Copy link
Member

@mihailik the tsconfig compiler options are used by the compiler, in this base implementation?

@mihailik
Copy link

On the versions: it would be FANTASTIC if parcel could build TypeScript out-of-the-box, without extra step of installing another package.

But if a project wants to pick a specific version, that should be used instead.

That sounds like a trivial setup: make parcel-bundler depend on typescript but in non-comittal version like >=1.0.0 or something.

@mihailik
Copy link

Yes @DeMoorJasper , tsc.js (which is TypeScript compiler) takes in account tsconfig.json if it exists in top directory and run without overriding --project myothertsconfig.json argument.

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Dec 10, 2017

The reason local requires are used is because of package size and speed, lots of people don't need typescript to be installed so it's not required by Parcel but if they want to have it they just install the official typescript package and they have it without even touching any config file.
This is the same for every non-standard language in here (less, stylus, ...)
There is also a plugin for advanced typescript support including typechecking and all the other fancy things

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Dec 10, 2017

You're getting me kinda confused about config files here, tsconfig files in parcel are loaded the same way we handle the babel config or any other config. @mihailik

let tsconfig = await config.load(this.name, ['tsconfig.json']);

// Overwrite default if config is found
if (tsconfig) transpilerOptions.compilerOptions = tsconfig.compilerOptions;
transpilerOptions.compilerOptions.noEmit = false;

@mihailik
Copy link

mihailik commented Dec 10, 2017

@DeMoorJasper quite reasonable on the size.

However TypeScript actualy only needs several files: tsc.js and several lib*.d.ts declarations. The rest is international language translations, IDE integration support and such. Those few required files take around 7Mb in current TS version.

@mihailik
Copy link

For context: I've been following and contributing a few small bits to TypeScript since early, concerning compatibility and unusual integration scenarios. And totally agree with parcel's concerns in bundlers like webpack and browserify - so I'd love to help on TS integration, in whatever way fits with project's vision.

@DeMoorJasper
Copy link
Member

@mihailik Feel free to open up a new RFC in issues with the idea's you have to improve Typescript support within parcel, i'm happy to help improve the typescript support in any way.

@cosmoKenney
Copy link

@mihailik I'm not following your suggestion to use defaults. Are you suggesting that tsconfig.json should not be supported by Parcel? I, for one, have hundreds of .ts files and do not want them compiled in place by tsc to seperate .js files. They end up getting commited/checked-in by other developers and causing all kinds of merge problems. I would love to see a tsconfig.json file supported out of the box by Parcel.

@hettiger
Copy link

hettiger commented Oct 16, 2018

TypeScript support seems to work pretty fine already.
But I'm not sure how to get Polyfills?
I'd love to just add a .browserslistrc and have it work.
Is it possible yet or should I move to Webpack for now?

EDIT:

I ended up using https://github.com/ryanelian/ts-polyfill and applying the correct libs configuration in tsconfig.json.
I'm quite happy with this solution. It doesn't add that much overhead. I'm still using the original TypeScript compiler. If I'm about to use a feature that's missing PHPStorm Inspector will error on me.

@csillag
Copy link

csillag commented Oct 19, 2018

For me, TS compilation works fine, but for some reason, I can't see any errors/warnings from the compilation process. Does parcel intentionally swallow error messages? Is there any way to change that configuration?

Thank you for explaining.

@ixrock
Copy link

ixrock commented Dec 31, 2018

@csillag i guess it's because parcel don't use tsc for compilation *.ts files at all (it's transpiled by babel which don't care about type-checks, etc.).

wbinnssmith pushed a commit that referenced this issue Dec 7, 2019
Add pipeline steps for measuring warm build perf

Approved-by: Will Binns-Smith <wbinnssmith@atlassian.com>
AGawrys pushed a commit that referenced this issue Dec 7, 2020
Skip AssetGraphBuilder test like upstream

Approved-by: Maia Teegarden
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

No branches or pull requests