Reputation: 119
this is driving me crazy.
I keep getting an error like:
'Type '{ habilete: number; endurance: number; hit: (damage: number) => void; }' is missing the following properties from type 'Monster': _habilete, _endurancets-plugin(2739)'
What I have:
export abstract class Fighter {
constructor(habilete: number, endurance: number) {
this._habilete = habilete
this._endurance = endurance
}
public get habilete(): number {
return this._habilete
}
protected set habilete(value: number) {
this._habilete = value
}
private _habilete: number
public get endurance(): number {
return this._endurance
}
protected set endurance(value: number) {
this._endurance = value
}
private _endurance: number
public hit(damage: number) {
this.endurance -= damage
}
}
Then Monster simply extends it with nothing more (for now):
export class Monster extends Fighter {}
Then I want to use it like:
<template>
<Card v-for="(monster, i) in gameStore.monsters" :key="i">
<MonsterSlot :monster="monster" />
</Card>
</template>
But on that :monster="monster", it will keep telling me that error I've pasted. MonsterSlot is simply:
<template>
<Flex v>
<Stat name="Habileté" :value="monster.habilete" />
<Stat name="Endurance" :value="monster.endurance" />
</Flex>
</template>
<script setup lang="ts">
import { Monster } from '@/model/Monster'
import Flex from './Flex.vue'
import Stat from './Stat.vue'
defineProps<{
monster: Monster
}>()
</script>
And yes, I'm using Vue.js but I do believe this is a TypeScript issue. Because, guess what... if I just put _habilete and _endurance in public on Fighter, it just works like magic...
But why? I don't want to expose my variables just to "make it work". I want them to have a public getter and protected setter. Doesn't seem complicated :(
Thanks for any tip! I must be misunderstanding something here.
Upvotes: 1
Views: 38
Reputation: 222309
There are multiple pitfalls associated with the reactivity of classes, this makes them much less practical than plain objects.
In this case monster
is not an instance of Moster
but a reactive proxy, i.e. reactive(new Monster(...)
, which is not the same thing. The refs inside instance properties are unwrapped at runtime. At compile time only the public properties of Monster
are processed, this is reflected in the error. And private fields are a known way to enforce type incompatibility in TypeScript.
If it's known that monster
isn't affected by ref unwrapping and effectively has Moster
type, it needs to be typed accordingly:
const monster = reactive<Monster>(new Monster(...));
Otherwise it needs to be taken into account that monster
prop is not Moster
:
defineProps<{
monster: UnwrapNestedRefs<Monster>
}>()
Upvotes: 0