Subscribe on changes!

script block next to script setup is in TSX mode by default

avatar
Jul 12th 2021

Version

3.1.4

Reproduction link

https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHRlbXBsYXRlPlxuICA8aDE+e3sgbXNnIH19PC9oMT5cbjwvdGVtcGxhdGU+XG5cbjxzY3JpcHQgbGFuZz1cInRzXCI+XG5cdGxldCB4ID0gPGFueT4zNDtcbjwvc2NyaXB0PlxuXG48c2NyaXB0IHNldHVwIGxhbmc9XCJ0c1wiPlxuY29uc3QgbXNnID0gJ0hlbGxvIFdvcmxkISdcbjwvc2NyaXB0PiJ9

Steps to reproduce

Use script setup with lang="ts", add a regular <script lang="ts"> block next to it, containing a cast.

What is expected?

Compiles fine.

What is actually happening?

Compilation error, seems like the script block is handled as TSX by default.


Regular TS and TSX are not compatible, there are ambiguities with casts and (sometimes) generic syntax. Users should opt into TSX with lang="tsx".

avatar
Jul 12th 2021

Does this happen in other cases than the old version of casting? You should use as any instead as it was introduced in TS to avoid this kind of issues. (https://github.com/vuejs/vue-next/issues/3598)

avatar
Jul 12th 2021

I wasn't aware this syntax was old or not recommended. The official docs say:

You can also use the angle-bracket syntax (except if the code is in a .tsx file), which is equivalent

And in the as section:

Since the above syntax cannot be used in .tsx files, an alternate type assertion operator should be used: as. The example can easily be rewritten with the as operator.

Doesn't sound very deprecated to me.

To answer your quetion: yes there are other syntactic ambiguities, related to generics. See for example: https://stackoverflow.com/questions/32696475/typescript-tsx-and-generic-parameters

I think there's a reason why TS has a flag to opt into the TSX syntax, and it would be good if Vue followed suit. It's not nice to have to come up with work-arounds to perfectly valid code.

avatar
Jul 12th 2021

Thanks for the links! So the as cast can always be used while the other one cannot. That is enough of a reason to not use the half working syntax. After all, the as cast was introduced because of the incompatibility of the old cast syntax with jsx.

If right now tsx works in lang=ts, introducing the change you are suggesting is a breaking change.

https://stackoverflow.com/questions/32696475/typescript-tsx-and-generic-parameters

That one works in the SFC playground.

avatar
Jul 12th 2021

I agree using as instead of cast is not a big deal. Generics problems can be complex to work-around as demonstrated in the SO discussion.

That one works in the SFC playground.

For the anecdote, generics problems happen. I had opened an issue in eslint-vue plugin exactly for that, some of my generic code was not parsing correctly. (and eslint-vue was changed to take tsx as an option).

If right now tsx works in lang=ts, introducing the change you are suggesting is a breaking change.

Is it really?

I think regular <script> components are not affected by that, as the code is just passed through. In fact, when I opened the eslint issue, I had no compilation problem, just linting.

So if this is specific to script setup compilation, then it's still marked as experimental and this is the last moment to fix it!

avatar
Jul 12th 2021

So if this is specific to script setup compilation, then it's still marked as experimental and this is the last moment to fix it!

That's true! It would be acceptable to change the behavior right now and I doubt it will affect a lot of people.

I haven't tried the different combinations but keeping the behavior coherent between different usages of setup to either handle TSX/JSX or not is more important IMO because it's easier to debug an invalid <any> cast in TSX (the error is very easy to lookup on the internet) than the same script behaving differently because it is next to a setup script and need a change of the lang to tsx.