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

Type mismatch on v-model #512

Closed
qgates opened this issue Sep 20, 2021 · 2 comments
Closed

Type mismatch on v-model #512

qgates opened this issue Sep 20, 2021 · 2 comments
Labels
question Further information is requested

Comments

@qgates
Copy link

qgates commented Sep 20, 2021

Doubt this is a bug but wondering the best workaround, since switching to volar it's reporting error in the template. I have an object along the lines of the following:

interface Lbe {
  ...
  data?: string | Date
}

Then in my SFC:

<template>
  <div>
    <textarea v-model="entry.data"></textarea>
  <div>
</template>
<script lang="ts">
  export default defineComponent({
  ...
    data() { return {
      ...
      entry: {} as Lbe,
    }}
    ...

Volar shows an ts2322 (not assignable to type) error on 'v-model' because the type description on TextareaHTMLAttributes.value is string | number | string[] | undefined, where my type has the possibility of data being a Date type.

I'm wondering the best way to handle such situations. In real world entry is an array of Lbe objects with data for textarea, input and a custom component which has Date for the data. We can't use type annotation in the template, so what's the best workaround here?

TIA 🙂

@johnsoncodehk
Copy link
Member

The solution depends on the actual situation and your needs, you can do

  • <textarea v-if="typeof entry.data === 'string'" v-model="entry.data"></textarea>
  • <textarea v-model="String(entry.data)"></textarea>
  • <textarea v-model="entry.data.toString()"></textarea>
  • ... or any way.

And typescript is supported in template now: https://twitter.com/youyuxi/status/1439304854028029953

@johnsoncodehk johnsoncodehk added the question Further information is requested label Sep 20, 2021
@qgates
Copy link
Author

qgates commented Sep 21, 2021

Thanks for your response and info @johnsoncodehk. On further investigation...

<textarea v-if="typeof entry.data === 'string'" v-model="entry.data"></textarea>
...is workable in the given example but fails with the same type mismatch error when entry.data is in fact entries[index].data, where <textarea> is inside a <div v-for="(x, index) in arr">

<textarea v-model="String(entry.data)"></textarea>
<textarea v-model="entry.data.toString()"></textarea>
...these approaches result in the following error in IDE and during template compilation on the v-model expression:

v-model value must be a valid JavaScript member expression. vue(42)

The only solution I've found that compiles and throws no IDE error is to replace v-model with the following:

<textarea
  :value="lbe_columns[index].data as string" @keyup="evt => lbe_columns[index].data = (evt.target as HTMLTextAreaElement).value">
</textarea>

The problem is that this isn't exactly semantic and bypassing v-model with v-bind/@event combo.

It's interesting to note that v-bind expressions allow TS typehint :value="lbe_columns[index].data as string" whereas v-model does not. Could this be something that might be improved upstream?

ps. thanks for your excellent work on Volar 👍🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants