For anyone that hits this again in the future, this is my simple solution without re-assigns and reactive concerns. The usual case is setting a class instance in a reactive object and let the UI update based on class internal properties.
Spoiler: do not use constructor, use a setup method and trigger it on onMounted life cycle.
Let's consider the class:
class MyClass {
data!: SomeType
constructor (data: SomeType) {
this.data = data
}
public someMethod () {
// ...method logic
}
}
On a component script we intuitively do the following
const classInstance = reactive(new MyClass(data))
This won't make classInstance.data reactive because its initial value is undefined until the constructor completes.
Instead, change the class implementation to:
class MyClass {
data!: null | SomeType = null
setup (data: SomeType) {
this.data = data
}
public someMethod () {
if (!this.data) return ...
// ...method logic
}
}
Back at the component file, use setup on onMounted life cycle hook.
const classInstance = reactive(new MyClass())
onMounted(() => classInstance.setup(data)
There is the obvious downside that every class method needs to check for null values on all initial properties but, imo, its wayyyyyy better that 'hacking' the reactive behaviour in Vue.