Skip to content

Incorrect TS issues being reported after upgrade to 2.2.6 #5227

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

Closed
richmason opened this issue Mar 2, 2025 · 13 comments · Fixed by #5229
Closed

Incorrect TS issues being reported after upgrade to 2.2.6 #5227

richmason opened this issue Mar 2, 2025 · 13 comments · Fixed by #5229

Comments

@richmason
Copy link

Vue - Official extension or vue-tsc version

2.2.6

VSCode version

1.97.2

Vue version

3.5.13

TypeScript version

5.7.3

System Info

package.json dependencies

Steps to reproduce

Create a SFC with a v-model that accepts different types, such as:

const model = defineModel<string | number>({
    required: true,
});

Then use the component:

const testValue = ref("Hello, World")
<MyComponent v-model="testValue" />

What is expected?

Given the following is valid TS:

let test:string | number = "test"
test = 8;

There should be no TypeScript errors.

What is actually happening?

The following error is being displayed in VSCode:

Type 'string | number' is not assignable to type 'string'.
  Type 'number' is not assignable to type 'string'. ts-plugin(2322)

Link to minimal reproduction

https://github.com/richmason/vue-ts-issue

Any additional comments?

This was not an issue in version 2.2.4

@Yizack
Copy link

Yizack commented Mar 2, 2025

@KazariEX
Copy link
Member

KazariEX commented Mar 2, 2025

This is expected behavior, since v-model is two way bindings. It requires that the variable passed in is strictly consistent with the type of model value.

@KazariEX KazariEX closed this as not planned Won't fix, can't repro, duplicate, stale Mar 2, 2025
@KazariEX KazariEX added question Further information is requested and removed pending triage labels Mar 2, 2025
@wiidede
Copy link

wiidede commented Mar 2, 2025

This is expected behavior, since v-model is two way bindings. It requires that the variable passed in is strictly consistent with the type of model value.

But, why? Parent component model value is string, why could the update event become string | number only because the child component supports number? Shouldn't it be consistent with the model value's type string?

This change seems causes a huge amount of v-model type errors.

@Yizack
Copy link

Yizack commented Mar 2, 2025

This is expected behavior, since v-model is two way bindings. It requires that the variable passed in is strictly consistent with the type of model value.

Though there are cases that for reusability we'd like to accept two types or more, this restriction is messing with so many uses

@wiidede
Copy link

wiidede commented Mar 2, 2025

@KazariEX
I still think defineModel's behavior is like

<script setup lang="ts" generic="T extends string | number">
const props = defineProps<{
  modelValue: T
}>()
const emit = defineEmits<{
  'update:modelValue': [value: T]
}>()
</script>

rather than

<script setup lang="ts">
const props = defineProps<{
  modelValue: string | number
}>()
const emit = defineEmits<{
  'update:modelValue': [value: string | number]
}>()
</script>

@KazariEX
Copy link
Member

KazariEX commented Mar 2, 2025

So why don't you write like:

<script setup lang="ts" generic="T extends string | number">
defineModel<T>();
</script>

?

@wiidede
Copy link

wiidede commented Mar 2, 2025

So why don't you write like:

<script setup lang="ts" generic="T extends string | number"> defineModel(); </script>

?

Because many components(also from library) write defineModel<string | number> and v2.2.6 break it.

@KazariEX
Copy link
Member

KazariEX commented Mar 2, 2025

You can report those issues to the upstream libraries and pin the version at v2.2.4. Anyway, the current behavior is inevitably brought through the implementation of two way bindings of types.

@KazariEX
Copy link
Member

KazariEX commented Mar 2, 2025

It seems difficult to implement complete type checking in these upstream component libraries😅We should make this feature default to false and opt-in.

@KazariEX KazariEX reopened this Mar 2, 2025
@KazariEX KazariEX added ❗ p4-important and removed question Further information is requested labels Mar 2, 2025
@pzgz
Copy link

pzgz commented Mar 2, 2025

it would be nice if there can be an option to not opt-in this feature, there're just too many errors after upgraded to 2.2.6, considering this is just a minor version upgrade, and the changes brought are breaking.

Can understand the requirement of type checking on two way bindings. But it's pretty tricky actually. Most of time, for example, there's a component has v-model supporting string | number, let's say it's a radio, and then we assigned it to a ref which is a number, we can do so because all the radio options are number. But I don't think compiler should have the obligation to check all this kind of situation. Maybe developers themself should take the responsibility, but for now, if we don't cast in v-model binding, it just stop from compiling.

@KazariEX
Copy link
Member

KazariEX commented Mar 2, 2025

In the case you mentioned generics are the most suitable.

@KazariEX KazariEX closed this as completed Mar 2, 2025
@KazariEX
Copy link
Member

KazariEX commented Mar 2, 2025

Please update to v2.2.8.

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.

5 participants