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

fix: use .ts/.tsx extension for internal virtual .js/.jsx codegen files #3353

Closed
wants to merge 7 commits into from

Conversation

rchl
Copy link
Collaborator

@rchl rchl commented Jul 2, 2023

This ensures that the virtual files use ts instead of js and tsx instead of jsx extensions. The main reason for me was to make the experience better when looking at virtual files written using Write Virtual Files command but I've also noticed that it improves behavior in one of the tests.

In #3121 a Non-null assertions can only be used in TypeScript files.ts(8013) was fixed and a test added. While the error was no longer shown, the type of slotFilters was incorrectly inferred as any. With this change, the type is actually correct and the test complains about slotFilters being undefined so added the missing variable.

Resolves #3347

@rchl
Copy link
Collaborator Author

rchl commented Jul 5, 2023

Sorry, I'm not getting this example (it could be just me not being familiar enough with the code).

In your example you have a JS script block that uses typescript syntax. I can fully get why that won't work. But my change, to me at least, doesn't seem relevant to that as I'm changing extension of the internal generated files that contain typescript code already.

johnsoncodehk added a commit that referenced this pull request Jul 13, 2023
@johnsoncodehk
Copy link
Member

I added a failed test to illustrate this.

@rchl
Copy link
Collaborator Author

rchl commented Jul 13, 2023

I added a failed test to illustrate this.

Still don't quite get your point. This test errors with

#3353/main.vue(2,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

which to me looks like a valid error since the argument to at is expected to be a number.

To me this looks like a change for the better - it catches an issue that wasn't caught before?

@rchl
Copy link
Collaborator Author

rchl commented Jul 13, 2023

And if your point is that Volar doesn't highlight the error in the editor then I can also see that behavior in the currently released v1.8.4.

rchl added a commit to rchl/vue-language-tools that referenced this pull request Jul 13, 2023
* origin/master: (25 commits)
  chore: fix typo (vuejs#3399)
  chore: bump volar
  Deprecate language server `json.customBlockSchemaUrls` option (vuejs#3398)
  Use faster method after config change (vuejs#3393)
  test: change defineComponent to support JSX (vuejs#3384)
  fix(class references): non scoped classes resolution regression (vuejs#3381)
  perf: hoist regexp if possible (vuejs#3378)
  fix: camel case components is not recognized as used (vuejs#3377)
  fix: allow slots to have no arguments (vuejs#3376)
  fix: don't remove comments when comment is in the first line (vuejs#3365)
  chore: add test for vuejs#3353
  chore: check project kind
  feat(typescript): implement `getExternalFiles`
  chore: update lock
  chore: remove resolve tsconfig warn
  ci(language-service): update html data
  chore: remove serverStats command from package.json of VSCode extension (vuejs#3366)
  v1.8.4
  chore: changelog
  chore: unpin volar
  ...
@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

@johnsoncodehk would you be able to respond to my comments?
To summarize: I still can't see any issues that this causes but I can see that it improves some cases.

@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

This generally improves cases when vue component uses JS instead of TS.

#3350 also made the original issue worse, making this fail in more cases. For example this PR also fixes a case like below where number-prop is not properly validated.

main.vue

<template>
    <div>
        <my-component number-prop="not_a_number" />
    </div>
</template>

<script>
import { defineComponent } from 'vue';
import MyComponent from './my-component.vue';

export default defineComponent({
    components: {
        MyComponent,
    },
});
</script>

my-component.vue

<template>
    <div>hi from my component</div>
</template>

<script>
export default {
    props: {
        numberProp: {
            type: Number,
            required: true,
        },
    },
};
</script>

@johnsoncodehk
Copy link
Member

johnsoncodehk commented Jul 26, 2023

We need to make sure that lang="js" (default lang) is consistent with the behavior of .js, if you create a .js file and write ''.at('0'); you will not see errors unless explicitly enable checkJs in tsconfig.

In addition to causing inconsistencies, I believe these checks are unexpected for many JS users.

@johnsoncodehk
Copy link
Member

johnsoncodehk commented Jul 26, 2023

#3350 also made the original issue worse, making this fail in more cases. For example this PR also fixes a case like below where number-prop is not properly validated.

This case is not because #3350, it's because defineComponent cannot provide $props type in js for my-component.vue.

https://play.vuejs.org/#eNp9UU1PAjEQ/SuTxgRIyHLgtqJGDQc9IFGPjQnuDljcndZ+AIbsf3fahZUYdQ/b9r03nfeme3FtTLYJKHIxcYVVxl9KUrXR1sMeSlwqwlvNZ0Ly0MDS6hp6XNA7lySp0OQ8RAFc/FT395IAjNXG5ZD2ABTqV7RzxjoIwH8azGGWqOERtPgRlMUyB28DHuAmrfHfDFL/PuE2te8PBtlZ6iVpNGqvaL+XK0mT0SGbGArv2PRSrbK108Sxkw0pCr5EVWgfjFccSorOoBSLqtLb+4SdmOGaNyzef8HXbhcxKeYWHdoNStFxfmFX6Ft6+jTDHe87stZlqFj9D/mITlchemxlN4FKtn2iS27v0hMqWj276c4juWOoaPQ4xKjmp4zz+yv6t91xNk51PHvRfAE5f7fS

The behavior of this PR is the same as manually replacing all <script> in the project with <script lang="ts">. Will you consider doing this?

@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

The behavior of this PR is the same as manually replacing all <script> in the project with <script lang="ts">. Will you consider doing this?

What do you mean? Where are you suggesting this should be done? In the Volar's code?

@johnsoncodehk
Copy link
Member

I mean you can add lang="ts" to SFC script blocks with global replace in your project, so you end up seeing the same type behavior as the result of this PR.

@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

No, I can't do that. My project will not support TS in script blocks by default. Volar would be fine with that but Webpack won't unless I'll add extra loader.

This suggestion is kinda missing the point though. We are looking into fixing an issue in Volar, not changing the project to workaround the issue.

Also note that I'm seeing different results in Vue 2 and Vue 3 with latest Volar release (without this fix):

Vue 3:

Screenshot 2023-07-26 at 21 10 11

Vue 2:

Screenshot 2023-07-26 at 21 13 26

So the issue you've pointed out with $props only affects Vue 3.

@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

Also, you still haven't pointed out any downsides of this change so I'm not sure why are you hesitant in doing that.

@johnsoncodehk
Copy link
Member

I've answered that it causes the script block default type behavior to be inconsistent with .js, it's not a matter of trade-off, consistency is a necessary feature.

If you really need to solve it from Volar, you can consider updating the PR to make the default language user-configurable instead of fixed ts.

@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

I've answered that it causes the script block default type behavior to be inconsistent with .js, it's not a matter of trade-off, consistency is a necessary feature.

Sorry but I don't see any specific arguments for where it creates inconsistency.

This change affects the type and extension of codegen files. Having those have JS type is IMO never correct because those are typescript files with type annotations and other typescript specific code.

When using the "Write Virtual Files" command and opening them in the editor, typescript will highlight many issues (mostly Type annotations can only be used in TypeScript files. ​typescript(8010)) with the files as they are clearly not JS files.

@rchl
Copy link
Collaborator Author

rchl commented Jul 26, 2023

We need to make sure that lang="js" (default lang) is consistent with the behavior of .js, if you create a .js file and write ''.at('0'); you will not see errors unless explicitly enable checkJs in tsconfig.

In addition to causing inconsistencies, I believe these checks are unexpected for many JS users.

Sorry, I've missed this argument before as it was followed by another comment immediately.

I see how this change could surprise some users that don't have checkJs enabled and don't expect to see any errors.

OK then, would it make sense to then only apply this logic when writing generated codegen files to disk? That was my original motivation anyway.

@rchl
Copy link
Collaborator Author

rchl commented Aug 2, 2023

I now agree with you about this change being wrong in a way but at the same time looking at virtual files and seeing a bunch of errors from TS doesn't seem right either:

Screenshot 2023-08-02 at 23 37 48

Not sure if there is a better way to handle this in TS.

For now closing this and extracting the changes to tests into #3353

@rchl rchl closed this Aug 2, 2023
@rchl rchl deleted the fix/js-codegen branch August 2, 2023 21:39
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

Successfully merging this pull request may close these issues.

"Write Virtual Files" command writes typescript files with .js extension
2 participants