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

Vue 2 cannot assert type in template #1354

Closed
jaredmcateer opened this issue May 26, 2022 · 3 comments
Closed

Vue 2 cannot assert type in template #1354

jaredmcateer opened this issue May 26, 2022 · 3 comments
Labels
question Further information is requested

Comments

@jaredmcateer
Copy link

jaredmcateer commented May 26, 2022

Minimal test case

https://github.com/jaredmcateer/vue2-volar-type-error

Issue explanation

When passing an object with a variable key to :checked on an input element I am getting a type error where the types might not align.
I've tried various ways of calming the error but have not found an ideal solution.

image

<script lang="ts">
import { defineComponent, PropType } from "@vue/composition-api";

export default defineComponent({
  props: {
    features: { type: Object as PropType<Record<string, string | boolean>>, required: true }
  },
  data() {
    return {
      feature: 'foo',
    };
  },
});
</script>
<template>
  <div>
    <h2>Error in ide</h2>
      <label>Checkbox <input
        type="checkbox"
        :checked="features[feature]"
        ^------- Type 'string | boolean' is not assignable to type 'any[] | Booleanish | Set<any> | undefined'
      />
     </label>
  </div>
</template>

I tried changing the line to :checked="(feature[feature] as boolean)" which calms the error in the IDE but is a runtime error (unexpected token)

image

Other things I've tried is adding:

v-if="typeof features[feature] === 'boolean'"

and

adding a method that has a type predicate

methods: 
  isBoolean(feature: any): feature is boolean {
    return typeof features[feature] === 'boolean';
  }
}

with

v-if="isBoolean(features[feature])

But these do not work. However if I try them with accessing the property directly such as:

<label>Checkbox <input
  type="checkbox"
  v-if="isBoolean(features.foo)"
  :checked="features.foo"
  />
</label>

Then it works (but doesn't for my real world usage)

@hexf00
Copy link

hexf00 commented May 27, 2022

It seems that your error prompt is not caused by volar, your ide type interface works correctly.
but I found that type assertion syntax(as xxxx) cannot be used in template in vue2. I think this is related to the compiler used in vue2.

I think the reason why your last code can work is that TS has a feature that context judgment can narrow the range of types.

Maybe you can try,it works well with me

<input  type="checkbox"  :checked="isBoolean(features[feature])"  />

@jaredmcateer
Copy link
Author

jaredmcateer commented May 27, 2022

Technically that would work but :checked="typeof features[feature] === 'boolean'" isn't the same as :checked="features[feature]". But I get from what you're saying my solution would be to use a method with a boolean return type or .

@johnsoncodehk
Copy link
Member

Hi @jaredmcateer, please try

<script lang="ts">
import { defineComponent, PropType } from "@vue/composition-api";

export default defineComponent({
  props: {
-    features: { type: Object as PropType<Record<string, string | boolean>>, required: true }
+    features: { type: Object as PropType<Record<string, 'true' | 'false' | boolean>>, required: true }
  },
  data() {
    return {
      feature: 'foo',
    };
  },
});
</script>

@johnsoncodehk johnsoncodehk added the question Further information is requested label May 28, 2022
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

3 participants