Typings error for an reactive object when a property is an Interface that has a private member
Version
3.0.2
Reproduction link
https://codesandbox.io/s/focused-ives-64y66?file=/src/useWallet.ts
Steps to reproduce
If you check the Codesandbox example, file useWallet
hover on the line 33
you will see the issue that happens.
This doesn't happen on a barebone typescript project (as shown here Typescript Example)
What is expected?
The person
property to have the Person
type.
What is actually happening?
The person
property has an "objectfied" Person
type.
This happens only when there are private properties to the interface.
The problem is located here:
The index signature makes TS loose the Person
type and only contains public properties.
Plain TS example:
This will be one for the TS experts (so not me)
workaround
reactive(state) as State
Update:
This solves the immediate error but dts tests currently fail on unrelated code for me locally so I can't completely verify:
This breaks unwrapping.
type UnwrappedObject<T> = T & { [P in keyof T]: UnwrapRef<T[P]> } & SymbolExtract<T>
So this will probably have to stay a caveat that requires typecasting. We have to loose the T
type in order to have the Unwrapping of possibly nested Ref
s working.
In this specific scenario it means that the private field is "lost" and the class's type has to be cast manually.
when you convert an object to reactive
vue will unwrap all possible ref
properties, to do that we create a new type which should be identical to the original one (if no property was unwrapped). Usually typescript is able to automatically infer the correct type after unwrapping
, but because you have private name
, which is technically a property that you don't have access outside of your class, vue will not infer it.
But if you check the intellisense you will see the types provide the same method but typescript cannot infer the correct type, this again is caused by the private name
, for typescript to archive the private field
it basically hide it in a symbol
property:
class Person {
private name: string
}
// should have the equivalent type
const person = ()=> {
[Symbol('name')]: string
}
As for the new type creation vue needs to unwrap because of this:
class PersonOther {
name: Ref<number>
}
const a = reactive(new PersonOther)
a.name // is a string