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

New rule vue/require-typed-ref: disallow ref() without type parameter or argument #2105

Closed
Demivan opened this issue Mar 14, 2023 · 13 comments · Fixed by #2204
Closed

New rule vue/require-typed-ref: disallow ref() without type parameter or argument #2105

Demivan opened this issue Mar 14, 2023 · 13 comments · Fixed by #2204

Comments

@Demivan
Copy link
Contributor

Demivan commented Mar 14, 2023

Please describe what the rule should do:

Disallow calling ref() function without generic type parameter or an argument when using TypeScript.

With TypeScript it is easy to prevent usage of any by using no-implicit-any. Unfortunately this rule is easily bypassed with Vue ref() function. Calling ref() function without a generic parameter or an initial value leads to ref having Ref<any> type.

What category should the rule belong to?

[x] Enforces code style (layout)
[x] Warns about a potential error (problem)
[ ] Suggests an alternate way of doing something (suggestion)
[ ] Other (please specify:)

Provide 2-3 code examples that this rule should warn about:

Bad:

<script setup lang="ts">
const counter = ref() // Ref<any>

counter.value = 0
counter.value = '' // Would be caught if we had typed ref
</script>

Bad: (maybe as an option to disallow explicit any too)

<script setup lang="ts">
const counter = ref<any>() // Ref<any>
</script>

Good:

<script setup lang="ts">
const counter = ref(0) // Ref<number>

conter.value = '' // Will result in a typecheck error
</script>

Good:

<script setup lang="ts">
const counter = ref<number>()
</script>

Additional example by @FloEdelmann
Good:

<script setup lang="ts">
const counter: Ref<number | undefined> = ref()
</script>

Additional context

@FloEdelmann
Copy link
Member

Sounds good! As a name, I'd propose vue/require-typed-ref. Note that it should probably also treat const counter: Ref<number | undefined> = ref() as fine.

@FloEdelmann FloEdelmann changed the title Disallow ref() without a type parameter or an argument when using TypeScript New rule vue/require-typed-ref: disallow ref() without type parameter or argument Apr 21, 2023
@FloEdelmann
Copy link
Member

It probably also should not do anything in .js/.mjs/.cjs files and <script> blocks without lang="ts".

@FloEdelmann
Copy link
Member

And there could be an option requireExplicitType (default false) that would additionally also report ref(0) and require ref<number>(0) instead.

@Demivan
Copy link
Contributor Author

Demivan commented May 31, 2023

@FloEdelmann, I don't see a benefit of requireExplicitType. If ref has an argument, it would use its type.
Adding type annotation here does not improve type information.

It probably also should not do anything in .js/.mjs/.cjs files and <script> blocks without lang="ts".

I'm currently trying to implement this rule and want to check how to handle js files. Should there be a check for context.getFilename(), or should this rule be specified in ESLint overrides for TypeScript files and not check for the file name?

@FloEdelmann
Copy link
Member

Adding type annotation here does not improve type information.

However, the argument could be of type any, then adding an explicit type annotation would make sense.

Should there be a check for context.getFilename()

I think yes, then it would behave the same in <script> blocks without lang="ts" and .js/.mjs/.cjs files.

@Demivan
Copy link
Contributor Author

Demivan commented Jun 2, 2023

I have created a pull request: #2204

Small note: this rule will have the same issue as #1969

@Demivan
Copy link
Contributor Author

Demivan commented Jun 2, 2023

@FloEdelmann What do you think: should this rule check and report const count = ref(null) and const count = ref(undefined) as errors?

@FloEdelmann
Copy link
Member

Yes, I think so, if the automatically inferred type would be Ref<any> in these cases.

@Demivan
Copy link
Contributor Author

Demivan commented Jun 2, 2023

It is inferred as Ref<null> and Ref<undefined> - a ref that can only accept null and undefined respectively. Those types are type-checked, but are pretty much useless.

@FloEdelmann
Copy link
Member

Hmm, then won't the mistake come up later when trying to assign a different value to the ref? But I'm also fine with reporting those refs in the rule.

@Demivan
Copy link
Contributor Author

Demivan commented Jun 2, 2023

I found this in my project.

There is a prop that accepts null or string, ref that is defined using const msg = ref(null). Type-check is passing because they both can be null.

I think, it is not a common problem, but still should be a good idea to catch it early, during linting.

@Demivan
Copy link
Contributor Author

Demivan commented Jun 2, 2023

I can make it an option

@FloEdelmann
Copy link
Member

Let's report it without an option; we can still introduce an option later if someone finds a valid use case for those refs.

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

Successfully merging a pull request may close this issue.

3 participants