Subscribe on changes!

Computed properties cannot with different types in getter/setter in TypeScript

avatar
Dec 4th 2022

Vue version

3.2.45

Link to minimal reproduction

https://sfc.vuejs.org/#eNqVUk1LxEAM/StxLt2FbYseS7coIijoRQQvA9Jds7XS+WAmVaT2v5uZ6bpePbWZl7y8vGQSV9YWHyOKStR+73pL4JFGC0Oru60U5KVopO6VNY5gAoeHDeyNsiPhK8xwcEZBxgSZ1FLvjfYEL8p3sA2ptR7VDl2zOl8fwYQdGVaT1AAdUgWrNWybWFt8tMOIm4CwFkZiXEEig2/w5HrdxfxYL+lUxuTxy3JolnrmxmUJ9GXRHELzCp5dT+1uwOtFw+NJZ5jhL1N2wWMt5ZClthn0HrQhaL3vOx2YgMySkni4qC6Tm5GyJlR2aAk5AqjfzptpikbMc11yFF97zWqgiq3ZeIalgMv4yiGraRbvVlhQ69gzVgC3Tw/3dyHnZkCFmtZJe1wak57leRr6vxNAnjNDXf4qFxuRjiBXrS3evdF8Msn9BeBLqdI+whufRIileCOyvipLf9iHQ3v3hXFdyX+FGzX1Cgv0Kt858+nRMbEUgSKsTsw/487lnQ==

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>.

avatar
Dec 4th 2022

It will work if you set const _msg = ref<number | string>(1).

avatar
May 8th 2023

@otomad You need to do computed<string | number>({...) This is fully documented: https://vuejs.org/guide/typescript/composition-api.html#typing-computed

avatar
May 8th 2023

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

avatar
May 8th 2023

@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.

avatar
May 8th 2023

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

avatar
May 8th 2023

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 😊).