Computed properties cannot with different types in getter/setter in TypeScript
Vue version
3.2.45
Link to minimal reproduction
Steps to reproduce
Define a computed property, getter type is number
, setter type is number | string
.
The computed property type is WritableComputedRef<number>
.
And cannot set a string
to its value.
What is expected?
Can set both a string
and a number
to the value of computed property.
What is actually happening?
type 'string' is not assignable to type 'number'
System Info
System:
OS: Windows 10 10.0.22621
CPU: (8) x64 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
Memory: 1.66 GB / 11.80 GB
Binaries:
Node: 19.0.1 - D:\Program Files\nodejs\node.EXE
Yarn: 1.22.17 - ~\AppData\Roaming\npm\yarn.CMD
npm: 8.19.2 - D:\Program Files\nodejs\npm.CMD
Browsers:
Edge: Spartan (44.22621.819.0), Chromium (107.0.1418.62)
Internet Explorer: 11.0.22621.1
Any additional comments?
TypeScript is support different types for getter and setter now.
A suggested solution is to define the type of Writable Computed Ref as WritableComputedRef<number, number | string>
.
@otomad You need to do computed<string | number>({...)
This is fully documented: https://vuejs.org/guide/typescript/composition-api.html#typing-computed
You need to do
computed<string | number>({...)
@ferferga If you do computed<string | number>({...)
then computed's value will have type string | number
and not number
, so it's not a solution
@jacekkarczmarczyk What's the use case for this though? I think allowing this is error-prone.
Computed are derived state, and as such, the getter should have some relation with the setter.
With pure (non-reactive) variables, TypeScript doesn't allow to define a type for "getting" and another for "setting". Neither in classes. It's a bad design pattern. Why should this be in core?
Computed should not be treated like functions, but as variables (more precisely, getters)
I understand that the original poster's issue is that the original get value is just a number, so TypeScript just infers it as a number and needs additional info (in this case a type annotation) to know it can be a string too.
I've only pointed out that your "solution" is not a solution for the problem. Whether the feature can be implemented or not or what are the use cases is a different thing
Anyway, most probably it can't be implemented because of ts limitations, here's a long discussion on this topic: https://github.com/microsoft/TypeScript/issues/2521
I understand that the original poster's issue is that the original get value is just a number, so TypeScript just infers it as a number and needs additional info (in this case a type annotation) to know it can be a string too.
@jacekkarczmarczyk This is why I said it's a solution in my first message, since I believed it's a misconception (though probably I shouldn't have done that in the first place 😊).