'TypeScript error ts(2345) is incorrectly labeling the type of object in Vue v-for loop
I am using Vue single file components. Here is a small example showing my error:
<script setup lang="ts">
interface IDesign {
displacement_map_urls: { [key: string]: string }
}
const props = defineProps<{
design: IDesign
}>()
// function to convert string to title case
const toTitleCase = (str:string) => {
return str.replace(/\w\S*/g, function (txt:string): string { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() })
}
</script>
<template>
<div >
<div v-for="(url, face ) in props.design.displacement_map_urls">
<span>{{ toTitleCase(face)}}</span>
<span>{{ url }}</span>
</div>
</div>
</template>
Visual Studio Code underlines face
in the template with this error:
const face: string | number
Argument of type 'string | number' is not assignable to parameter of type 'string'.
Type 'number' is not assignable to type 'string'.ts(2345)
For some reason ts thinks that the face
variable is a string|number
, however if you look at the interface IDesign
you can see that the displacement_map_urls is an object with string keys and string values.
I think this has something to do with the Vue v-for
loop, because if I manually grab the first key without going through a v-for
loop then VSCode does not show an error:
{{ toTitleCase(Object.keys(props.design.displacement_map_urls)[0]) }}
Please let me know if I need to provide anything else to help solve this problem.
Solution 1:[1]
face
is the index into displacement_maps_urls. It is type string | number
because displacement_maps_urls could be an array (or an integer-keyed object). I think the parser isn't smart enough to always get the types of the Vue template properties right.
string | number
cannot be automatically cast to string
because sometimes it's a number. But since in your case you know it's always a string, you can just cast it manually (face as string
):
<template>
<div >
<div v-for="(url, face ) in props.design.displacement_map_urls">
<span>{{ toTitleCase(face as string)}}</span>
<span>{{ url }}</span>
</div>
</div>
</template>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dov Rosenberg |