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

Add native TS support for .vue files #238

Open
JessicaSachs opened this issue Apr 24, 2020 · 23 comments
Open

Add native TS support for .vue files #238

JessicaSachs opened this issue Apr 24, 2020 · 23 comments
Assignees

Comments

@JessicaSachs
Copy link
Contributor

Decide between ts-jest and babel-jest

@lmiller1990
Copy link
Member

Let's go with ts-jest, release v4 and call it a day.

Anyone up for this? It should be trivial.

@lmiller1990
Copy link
Member

lmiller1990 commented Apr 24, 2020

For reference see the next branch, which works with Vue 3 and uses ts-jest. This one won't give errors in vue files though. I wonder what I missed.

@lmiller1990
Copy link
Member

Actually, I do not think this is anything to do with ts-jest. We are using ts.transpileModule, which does not seem to do type checks. I will look at this today.

@lmiller1990
Copy link
Member

lmiller1990 commented Apr 25, 2020

Ok, so I figured out one way to do this. We can use this kind of thing to get errors. The downside is we must write the TS to a file to be consumed by this - not ideal for perf. But I will experiment. Most likely someone who works on Vetur has already solved this problem. I will ask them about it.

I will make a POC you can enable with a flag and we can release v4. Improving it can be a minor release.

I also fixed CI (I think). PR coming in the next day or so.

@lmiller1990 lmiller1990 self-assigned this Apr 25, 2020
@lmiller1990
Copy link
Member

Seems to work:

image

For now the test just runs anyway - should the test fail? Not sure the correct behavior here.

@JessicaSachs
Copy link
Contributor Author

If we're going with ts-jest, it should not fail. You can write TS code that won't compile and it'll pass unit tests.

ts-jest doesn't use the typescript compiler. This was the difference between ts-jest and babel-jest's expected behavior

@JessicaSachs
Copy link
Contributor Author

I think the dream is that we listen to the user's existing settings and use the ts-jest or babel-jest settings they have.

If TS users want their stuff to fail to compile during unit tests, then they want that for their SFCs, too

@lmiller1990
Copy link
Member

lmiller1990 commented Apr 25, 2020

Yep, I think we should just inherit the users' ts-jest settings. Eg, you can make your test run, despite TS errors using ts-jest, if you like, this is the main one I think we need to inherit. This one. I can make this change.

Anything else we will need to grab from their ts-jest settings?

@ahnpnl
Copy link

ahnpnl commented Apr 29, 2020

If we're going with ts-jest, it should not fail. You can write TS code that won't compile and it'll pass unit tests.

ts-jest doesn't use the typescript compiler. This was the difference between ts-jest and babel-jest's expected behavior

To be correct, ts-jest does use typescript compiler. It has 2 modes: isolatedModules: true which will use ts.transpileModule and isolatedModules: false will use LanguageService API.

There is one thing to use ts-jest is: since vue doesn't use ts or tsx extension, I don't know how internal ts-jest typescript compiler will handle compiling vue extension. But if just delivering ts to ts-jest, everything will just work normally.

@lmiller1990
Copy link
Member

lmiller1990 commented Apr 29, 2020

I got this working here @ahnpnl #239

not really ideal, but we just rip out the ts part of the Vue file and compile it manually using the typescript library. I don't have a good solution to "deliver" a ts file from a vue file.

Last thing I need to change is to inherit some settings from ts-jest - that is to use transpileModule or compile, depending what the user configured, then we can at least release this as experimental

@ahnpnl
Copy link

ahnpnl commented Apr 30, 2020

Just FYI from ts-jest side:

So I can see the approach you are using in #239 is similar to ts-jest 23.1.4, 23.10.5 is a rewritten version of ts-jest so most of stuffs are not the same anymore. For example:

  • isolatedModules: true:

    • 23.1.4: this is the default mode of ts-jest and if user wants to have type checking, there is a flag to enable it which will trigger creating TypeScript Program like you are doing with feat: type check vue files #239.

    • After 23.10.5: this is no longer the default mode of ts-jest due to lack of supporting some features (see https://kulshekhar.github.io/ts-jest/user/config/isolatedModules). Also the type check possibility is removed for the most to ultilize the most of speed when running tests.

  • isolatedModules: false (new feature):

    • This is the new default mode of ts-jest.

    • Run tests with TypeScript LanguageService API, which allows to ultilize full functionalities from TypeScript + type checking.

    • This mode is good, however there is a payoff for performance that the speed won't be as fast as isolatedModules: true, about 40-50% slower.

  • Recently we ts-jest also added partial support TypeScript projectReferences, see for isolatedModules: true and for isolatedModules: false

From #239 I don't see anywhere using ts-jest APIs. However, I'm not so familiar with vue-jest codebase so I just share my opinion. But if anything ts-jest can help, feel free to discuss with us :)

@lmiller1990
Copy link
Member

lmiller1990 commented May 1, 2020

So we need to check the user's ts-jest config and version then decide?

Reflecting on this more, although ts-jest is popular, it's not the only way to use TS in jest (can use babel).

Maybe we just have a similar option users can set for vue-jest. Eg:

vue-jest: {
  isolatedModules: true
}

And go with that. Coupling to another project's config (eg ts-jest) might not the make the most sense (although I love ts-jest), especially considering they could change their API at any time (like described above). We can just mirror the parts of the API that make sense.

@JessicaSachs what do you think? What we have here does satisfy the goal of "build in TS support". We just need to decide if we want the default to be to typecheck or not.

@ahnpnl
Copy link

ahnpnl commented May 1, 2020

I can summarize these below options:

  • If only type checking without using ts-jest, you don’t need to have the config isolatedModules: true above.

  • If delegates to ts-jest to compile ts and type checking, you will need to provide a config to use type checking or not type checking for vue-jest and default use ts-jest after 23.10.5, preferably 25.5.0 (which greatly improves performance for isolatedModules: false + projectReferences support, coming soon)

Caveats with only type checking without using ts-jest is losing some typescript functionalities.

Now ts-jest has a stable structure so these 2 modes of isolatedModules won’t change anymore (unless typescript removes their apis)

These are all the options I can think of from ts-jest side.

@lmiller1990
Copy link
Member

Ok, cool. ATM we do not delegate to ts-jest. I don't know enough about jest transformers to implement this at the moment. Maybe in the future, we can collab on this.

For now I am happy with the support here, so I will prepare to release this. Are you on any discord servers? I may ask you for help with improving ts-jest support for Vue files in the future.

@ahnpnl
Copy link

ahnpnl commented May 1, 2020

Ye you can contact me on discord @ahn#1702 or ts-jest Slack (link in ts-jest README).

I am curious about working a different file extension like .vue so trying out with vue is also in my to-do list. The goal is make a generic approach for other file extensions later which are not js or ts.

@lmiller1990
Copy link
Member

Basically we rip out the script part - so you are no longer working with a vue file at all, just a ts file. Any way to typecheck a TS file without the file actually existing on the disk? I had to write a temp file see here and re-read it (feels bad).

@ahnpnl
Copy link

ahnpnl commented May 1, 2020

you can use memory cache for that, see https://stackoverflow.com/questions/53733138/how-do-i-type-check-a-snippet-of-typescript-code-in-memory . I just tried out the codes provided there and it works. The example output like this

==== Output code ====
function foo(input) {
    console.log('Hello!');
}
;
foo('x');


==== Diagnostics ====
Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'.
Argument of type '"x"' is not assignable to parameter of type 'number'.

But to put that into a release, that example solution needs some fine-tunings :)

@lmiller1990
Copy link
Member

lmiller1990 commented Jul 2, 2020

Hi @ahnpnl , I am spending some time on this project now.

I have another question, which I am unsure how to resolve. If I have many components, they all import the same module (say, vue). When I set my config to "target": "es6", I get errors since it tries to do const vue_1 = require('vue') in every file, and since you cannot redefine a constant, it throws errors.

I have made a reproduction here: #249

Running the tests for this repro is pretty annoying, I had to do some hacks to get it working locally (I always hack this repo to do dev, idk how other people are doing it). I figured out might have some ideas around this? Just force it to compile to "es5" no matter what for the tests?

@ahnpnl
Copy link

ahnpnl commented Jul 2, 2020

Indeed I see with target: es6 the test doesn't work anymore. The stack trace points to @babel/parser so this one you might need to ask Babel team.

Side information: I have checked ts-jest regarding to compiling with virtual file path, it is actually already possible with current ts-jest version.

These tests don't require an actual physical file path but just simply need the file content. You can try out ts-jest apis for #239

@ahnpnl
Copy link

ahnpnl commented Jul 8, 2020

there is another way to tackle the problem happening to es6 is using babel plugin to alter AST (if using babel) or TypeScript AST transformer (if using ts-jest). Still this way looks like a workaround for me than actually solving the root problem.

@MikeBlandford
Copy link

Would this fix the issue of casts in vue files being compiled as jsx and crashing? vuejs/vue-test-utils#1358

@beamsies
Copy link

I'm having the same issue here: vuejs/vue-test-utils#1358

@lmiller1990
Copy link
Member

What does that issue have to do with this issue?

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

No branches or pull requests

5 participants