Closed bbugh closed 4 months ago
@phaux Not that simple:
tsc
does nothing in the typical Typescript folder structure. This command assumes you have configured a .tsconfig file, otherwise you need to pass additional parameters on the command line..js
file in your HTML, rather than the source .ts
entrypoint as is usually taught in the parcel guides, which adds in ambiguity (you need to know where that file will be compiled) and could throw off beginners.parcel index.html
and automatically re-run type checking when my files change.This requires you to point to the compiled .js file in your HTML, rather than the source .ts entrypoint as is usually taught in the parcel guides, which adds in ambiguity (you need to know where that file will be compiled) and could throw off beginners.
I don't think there's any reason to make it this complicated, tsc will pick up the entrypoint regardless and Parcel will still do it's thing. I've done this on many projects and it's far from this complicated.
@mattrossman
- This command assumes you have configured a .tsconfig file
Well, duh. This is how TypeScript works. Are you proposing that Parcel should ship it's own opinionated default tsconfig? Who decides which strict options are enabled, which DOM/ES libs you use, which target you want, where are your custom typings, etc?
- This requires you to point to the compiled
.js
file in your HTML, rather than the source.ts
entrypoint as is usually taught in the parcel guides
What? I think I don't understand. It's enough to just run tsc
in the console. There's a field "include"
in tsconfig but it's optional.
- this doesn't help during development where live reloads are important. I would expect a solution to work with
parcel index.html
and automatically re-run type checking when my files change.
I'd say that being able to live reload an application and use it even when types are wrong is a good thing for quick prototyping. You see the errors in the IDE anyways and you can always run tsc from console or configure Parcel plugin if you want the whole project checked.
I am honestly very confused about the parcel maintainers strong resistance to improving the language support!
I definitely understand where you're coming from about Babel with fast compilation. That is compelling and I think you're right that it's a good default. What I'm less clear on and haven't seen much discussion about is why there's no typing support at all by default. Parcel's main agenda seems to be bring "convention over configuration" to JavaScript land... except for TypeScript? If the instructions are always going to be "install typescript, run tsc --watch" why isn't that the default zero-config setting? Why do we need yet another terminal window for yet another command when it can be run in the bundler quite easily? 😳
With a couple of changes, Parcel could offer strong TypeScript support without losing the value that your implementation Babel brings. When a .ts
file is imported, Parcel only needs to:
typescript
package and generated a default tsconfig.json
with tsc --init
serve
(as a linter? with tsc --watch --noEmit
?)build
commands when there are type errors You still get the fast compilation with Babel and the fast development turnaround, but it operates more closely with the expectations of what "supporting typescript" really means. That's a significant improvement over what is happening now.
What do you think?
Well, duh. This is how TypeScript works. Are you proposing that Parcel should ship it's own opinionated default tsconfig? Who decides which strict options are enabled, which DOM/ES libs you use, which target you want, where are your custom typings, etc?
No, Parcel doesn't need to include an opinionated tsconfig.json
because you can already generate the Microsoft opinionated default tsconfig tsc --init
and it works fine with Parcel.
I think I mostly feel like we cannot win here. Some users want Parcel to do type checking and some don’t. Parcel has never done type checking by default. Even in v1 you needed to install a plugin. I’m happy to enable it by default, but it just feels like we’ll get a bunch of issues asking us to turn it off then, especially if it isn’t a better experience than using TSC directly. 🤷🏻♂️
Regardless of the default, the TS validator plugin and the validation infrastructure in general is a bit under used atm and needs some serious work. We need to make sure it updates properly when files change, handles caching correctly, supports various TS config options, etc. Would someone on this thread be willing to help out with that?
We’d love to make using TS with parcel a great experience but I’m not sure anyone on the core team has the time or knowledge about how to make that happen at the moment so we would very much appreciate some help. 😍
@devongovett I know I've been AWOL for the last month, but improving the type-checker is still a long-term goal of mine. FWIW, I'm also in the "turn it on by default" camp, esp. once we iron out all the kinks. I'd love some help, if anyone on this thread is interested.
babel-transformer
also does not seem to understand the as
keyword in, like foo as Type
. It is not accurate to call this TypeScript support; Parcel 2 is supporting whatever subset of it that babel-transformer
happens to understand. I think this has the potential to be extremely frustrating to end users who expect TypeScript support but run into babel-transformer
quirks; weighed up against that, requiring a tsconfig.json
is really not so bad, especially since reasonable defaults can be generated straight from tsc
. I mean, it's one of the first things that the TypeScript documentation states:
The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project
I may simply be mistaken about Parcel's design goals, but I took "zero-configuration" to mean not that there was literally zero configuration at all, but that you wouldn't have to configure Parcel itself. As in, if I wanted Parcel to bundle a Rust project I would expect to have to have a Cargo.toml
somewhere; that's what a Rust project is. It's a pretty common pattern on the Parcel v1 docs for various languages for them to recommend or require making configuration specific to that language; like a .sassrc
or .babelrc
or bsconfig.json
etc.. Likewise, if I am coding a TypeScript project, I expect to have a tsconfig.json
--that's what a TypeScript project is.
Just my 2c. Strongly in favour of making tsc
the default, as babel-transformer
doesn't (and can't) actually support TypeScript, in its entirety.
I think whether tsc
should yell at you with type errors when parcel
invokes it is a separate question to whether tsc
should be used for compilation. (Of course the answer is yes it should =), but it doesn't really matter to me since using my editor itself will yell at me for type errors as I go, and I suspect that would be the case for most people using TypeScript.) I thought the Parcel v1 pipeline of tsc->babel worked really well.
In any case, not validating types kind of defeats the point of TypeScript. To drive the point home: it's as if you didn't throw an error when a dependency wasn't found, and instead silently replace that dependency with null
in the generated JS; it isn't a syntactic error but it absolutely should be validated. So here's my take:
If a tsconfig.json
is present, compile with tsc
by default. If not, use the standard JS pipeline but validate the types after each build. My reasoning is that those who don't even spend the time to create a tsconfig.json
are just hacking together a prototype and will prefer faster builds over safer builds. I'd be willing to create a PR for this kind of system.
Personally, I don't think a bundler should run the type checker - a bundler's responsibility is to remove the types from the TS and convert it to JS as fast as possible. Putting the TS type-checker in the way of that slows the critical path a lot and adds a bunch of extra complexity to parcel when you want to make it fast (result caching, incremental builds etc )
It's likely anyone using TypeScript would already have their editors set up to show them the errors inline, and running tsc
from the command line is a perfectly normal final check for the whole project.
( To avoid adding to the noise in this thread, projects like svelte and vue have things like svelte-check and vti for the same purpose as tsc )
Often a change in one file causes a type error on the other side of the project. I can't imagine only running proper type-checking at the very end of development, particularly as someone who's very "type-driven".
Also running tsc
from the command line does not support .vue
files, others have commented about it in this thread. That is not a workable solution.
The only way to type check Vue is to build it into the build process in some way. Given that Vue 3 is in beta-almost-RC and it was rewritten in TypeScript and now has much better TS support, it's pretty important.
@orta I'm going to have to completely disagree with you. A build that is a bit sluggish but has correct results is merely inconvenient. A build that is fast but has incorrect results is useless. If I wanted “as fast as possible” and didn't care if my code is correct, I wouldn't be using TypeScript.
It's likely anyone using TypeScript would already have their editors set up to show them the errors inline
Editors cannot show all TypeScript errors. Editors also cannot show errors that occur in files other than the one being edited.
running
tsc
from the command line is a perfectly normal final check for the whole project.
No, it's not. Running your build system from the command line is a perfectly normal final check for the whole project. In a project using Parcel, that build system is Parcel, not tsc
.
I get that I'm posting in a thread that can realistically only be made up of people who disagree, but TypeScript always emits JS on purpose and has a compiler flag which you can turn on to get the workflow you're talking about ( noEmitOnError
) however the default (and how it works with tsc) is to not block JS emit on TypeScript errors.
Unless I'm misunderstanding I don't believe that's relevant, you'll still get type-checking. I personally don't care if it emits or not upon type-checking failing, only that there is type-checking and any errors are reported to me.
Based on the number of people on this thread, it seems supporting TS better is something we should work on. If I were to put together a plan for how we could accomplish the goals of this thread, would anyone be willing to help us implement it? There’s a lot more to this than just a config change, eg .vue/.svelte TS checking support is a big project on its own and not something that’s currently supported even with the existing plugins.
I'd be willing to help improve TypeScript support, especially with regards to Vue. In the Parcel 2 Vue transformer, TypeScript files are actually imported as separate assets from .vue
, which means that type-checking should be possible if the TS transformer could type-check.
@101arrowz typechecking does not and should not happen in a transformer, it will significantly slow down building. It happens in the typescript validator https://github.com/parcel-bundler/parcel/tree/v2/packages/validators/typescript
There's a lot more to typechecking in a tool like this than just calling tsc.
I'm not happy with performance being put ahead of safety, but since one of Parcel's core principles is being "blazing-fast," I suppose there really isn't any other option. My point is that TypeScript users, by nature of using TS over JS, have agreed to give up the rapid prototyping and monkeypatching capabilities of pure JS for more safety, and Parcel treating TS the same as JS might help prototyping but will make development more frustrating later on.
Regardless of the position the Parcel team chooses to take, the existing TS infrastructure could be improved upon, as you have mentioned, so I'll work on that for now.
The reason for not doing type checking in the transformer isn’t performance, but because it’s actually impossible to do it there. Type checking requires a full graph of files. It cannot be done just on a single TS file at a time. For example, you could have imported and exported types and values. Transformer plugins in Parcel operate on individual files, as they are discovered. Type checking must be done in a Validator plugin, at the end, once the full graph is known.
In order to support .vue type checking, we would need to store the TS asset that’s extracted by the transformer and somehow mark that for validation later. In the TS validator, when a .vue file is imported, we’d need to resolve that to just the TS part so that the TS compiler doesn’t need to worry about the other parts.
This thread is getting very long and there's lots of different features being requested here, so I've put together three separate issues to discuss them:
baseUrl
, paths
, and rootDirs
.const enum
s which require type information to compile and aren't supported by TSC's transpileModule
or Babel. In addition, type errors for .vue
/.svelte
files could be implemented this way. This is a much longer term solution that we can begin working toward, and once it's ready, it could potentially become the default.Please leave your feedback for the relevant feature on these individual issues. If anyone is interested in helping to implement them, please let us know. It would be greatly appreciated. 😄
I am happy to see there are issues now to improve the TypeScript support. The lack of TypeScript full adoption in Parcel has been a barrier to entry for us.
I have seen time and again people being either JavaScript or TypeScript people and neither understands the other side. If you truly use TypeScript you use it for the IDE intellisense and linting. But you also rely on the build failing when there are typing issues as those lead to edge and corner case bugs.
I also totally understand the decision to use Babel for transpiling and performance. I also think a fourth issue to add is rich documentation on how to add TypeScript support using Parcel v2 and the options you have like using the validator and what the functionality and purpose that supports. There is also adding ESLint functionality that fully supports TypeScript as well.
I did add the validator and that does break when running code in the "debug" mode of Parcel.
For me lack of error checking on the Parcel side makes Parcel useless to use during development. The perfect use case is that Parcel watches the files, and rebundles them when changes are detected. Errors are shown in the terminal output if any are found.
Without that functionality I have to run Typescript checker and Parcel bundler at the same time, and my PC begins to struggle
@kuba-orlik So the initial start of parcel --open
with the validator setup would error on a TypeScript problem. Also having ESLint properly setup with your IDE of choice (VS Code here) it highlights the issue. When building the validator kicks out an error and fails the build. The only time the build isn't errored out is on hot reloading. So, @devongovett would adding the validator to the hot reloading be part of #4937 or something that could be accomplished sooner? I also imagine it needs to take into account all validators that could error otherwise.
Considering how a setup of validator + ESLint works that is enough type checking and build failing for me to consider Parcel2 a comparable bundler to the CRA \ webpack setup. The tooling could improve and the issues above I think are seeking to close that gap.
EDIT: Just discovered that it still doesn't support 'baseUrl' so without that Parcel just has too many oddities to not be able to use it with TypeScript projects. It supports it but only in a minimal form.
For my particular setup it would be enough if:
parcel watch
output;build
commandFor contrast, I've been very happy with Next.js's out-of-the-box Typescript support. Just rename a file to .tsx, and you are basically good to go. Next automatically adds a tsconfig.json if it doesn't exist.
I'm not sure if it uses tsc or Babel — either way it's working very well.
Well, I came to this thread with I think, the very same great experience in mind: Typescript support in Next.js is good. So I was convinced there was type-checking in Next.js at every-level, as my day-to-day experience with it suggests.
I was wrong.
Next.js uses webpack with babel-plugin-transform-typescript and its caveats. So when you run Next.js in developpement mode, where things goes only through webpack, there is no type-checking and you can verify for yourself with:
console.log(props.DOES_NOT_EXISTS)
;
On the other hand if you look at where the build code flows, you will find verifyTypeScriptSetup with this code:
// Verify the project passes type-checking before we go to webpack phase:
return await runTypeCheck(ts, dir, tsConfigPath)
Some users want Parcel to do type checking and some don’t.
At the beginning I was in favor of it because of my experience with Next.js. But it's clear that Next.js, a kind of "zero-config" project, doesn't have it when in developpement mode (and it doesn't bother me) but have it when it comes to the build (and I think it's great).
So at the end of the day runTypeCheck (or whatever) && parcel build
does the trick for me.
No, it's not. Running your build system from the command line is a perfectly normal final check for the whole project. In a project using Parcel, that build system is Parcel, not tsc.
I also agree with that, oh men.
If someone just simply seeks a quick TypeScript + Parcel + Jest
(with allowed .js
files import) solution example:
npm i -D jest typescript ts-jest @types/jest babel-jest @babel/core @babel/preset-env
Add .babelrc.js
module.exports = {
presets: ['@babel/preset-env'],
}
Add jest.config.js
module.exports = {
transform: {
'^.+\\.(tsx|ts)?$': 'ts-jest',
'^.+\\.[t|j]sx?$': 'babel-jest',
},
}
Add tsconfig.json
{
{
"compilerOptions": {
"module": "commonjs",
"allowJs": true,
"strict": true,
"noEmit": true,
},
"include": ["src/**/*.ts"]
}
}
From package.json
...
"scripts": {
"start": "parcel serve ./src/index.html --port 3000",
"build": "tsc --noEmit && jest && parcel build ./src/index.html",
"type-check": "tsc --noEmit --watch",
"test": "jest --watch"
},
...
Hello there,
I think you've goon off topic abit, let me bring it back.
The point I make in my issue:
What % of TypeScript projects use a tsconfig.json?
I use a tsconfig in 100% of my TypeScript project, so in my case at least I am always going to manually configure to use tsc (which I never did in Parcel 1, it just worked)
Also:
for most cases developers will want to transform TypeScript as nature intended using tsc.
I think Parcel 2 should work the same as Parcel 1 with regard to TypeScript.
The reason that Babel is used is that it is a bit faster, but I am not concerned with speed, Parcel is fast enough, and TBH even if it takes seconds or minutes then I don't mind.
@mischnic I do like some of the quotes above:
I do hope the developers listen and will switch to tsc
by default.
I think Parcel 2 should work the same as Parcel 1 with regard to TypeScript.
Parcel 1 didn't do typechecking either.
I did notice that, but Parcel 1 used the tsconfig
.
How does Parcel 2 handle React?... I do not use React myself but the Parcel 1 docs show you need a option in tsconfig.
Presumably using React in Parcel 2 would require the tsc
config in the .rc
?
// tsconfig.json
{
"compilerOptions": {
"jsx": "react"
}
}
The default Babel config generated by Parcel 2 would include @babel/preset-env
, @babel/preset-typescript
, @babel/preset-react
in that case.
I have created the .parcelrc
config required for using TypeScript... I had two further errors because Parcel couldn't find the modules @parcel/transformer-typescript-tsc
and typescript
, so I had to npm i
thouse.
I would say this is a breaking change from anyone who used Parcel 1 and it breaks the 'no congfiguration' pholisophy.
You are welcome to submit a PR. Further complaining about this issue is pointless. We've created the issues linked in my above comment to make our intent clear. If you would like to help make that happen faster, please do.
At this point, I'm going to close this. Parcel is not a type checker and will probably never be one. I don't have the bandwidth to implement and maintain this but if someone wants to implement it as a third party plugin that would be great (I guess it could probably be implemented as a reporter). Otherwise, I recommend simply running tsc --noEmit
during your production build script and using TypeScript in your IDE during development.
I've been following #1378 for a long time, and I'm thrilled to see Parcel 2 taking on better first-class support for TypeScript. There's currently some problems with Parcel 2 out of the box, and I didn't see any threads tracking this, so I'm making an issue.
🐛 bug report
In 2.0.0-alpha.3.2, given a very basic TypeScript project, there are three issues:
typescript
package is not automatically installedtsconfig.json
are completely ignored🎛 Configuration (.babelrc, package.json, cli command)
Here's all of the files:
package.json
created from two commands:yarn init -y
yarn install -D parcel@v2
index.html
index.ts
tsconfig.json
to test, and it's obviously being ignored because parcel still compiles:🤔 Expected Behavior
As part of parcels "zero configuration", parcel automatically detects TypeScript and configures the project to correctly use TypeScript.
typescript
package should be installed automaticallytsconfig.json
should be read and used by whatever is compiling it, if it exists😯 Current Behavior
typescript
package is not automatically installedtsconfig.json
are completely ignored💁 Possible Solution
I'm guessing one of these two potential solutions:
transformer-babel
is correctly configured to behave as expected with TypeScript, extending from #3083typescript
and@parcel/transformer-typescript(-tsc?)
is automatically installed when Parcel 2 detects a.ts
file.Either one is fine, I think, as long as the TypeScript compilation actually behaves like TypeScript by default!
🔦 Context
babel
for TypeScript: https://github.com/parcel-bundler/parcel/pull/3083💻 Code Sample
See files above
🌍 Your Environment