const person = reactive({ firstName: "John", lastName: "Doe" }); // reactive field
const fullName = computed(() => `${person.firstName} ${person.lastName}`); // effect
console.log(`You are logged as: ${fullName.value}`); // Yo
console.log(`You are logged as: ${fullName}`); // Yo
computed = {
__v_isRef: true,
// expose effect so computed can be stopped
effect: runner,
get value() {
if (dirty) {
value = runner()
dirty = false
}
track(computed, TrackOpTypes.GET, 'value')
return value
},
set value(newValue: T) {
setter(newValue)
},
toString() {
return this.value // THIS
},
} as any
I'm not sure if this is a dumb suggestion, but would it be better if the return was return this.value.toString()? That seems like it might help support more types and nested objects.
@marcusball, toString() is not available on all types, try type 10.toString() into console.
Proper way is to use String.
toString() {
return String(value)
}
But is worth to check what does transpiled string interpolation. Maybe it does it automatically.
I don't think it is needed at all. Calling .value is more consistent with rest of the code. It would be really crazy to have half stuff with .value and half without it. (even when reactive object already does something similar) and template-compiler transpiles it in view.
PS: The value is there because you need to tell to the wrapper, you want to compute the value. (otherwise there is no way to detect when it should run)
@sionzeecz
try type 10.toString() into console.

@jacekkarczmarczyk
uh, I see, the first dot is used as decimal point and the second one for a function call.
More understandable for me looks String(10) than 10..toString().
Anyway thank you for a lesson :)
x.toString() throws if x is null or undefined.
String(x) handle those cases, but, in some cases, it can be misleading or opaque. Here are some examples:
String({}) === '[object Object]'String([]) === ''String([2]) === String(2)String('2') === String(2)Vue already has a good stringifier, that fallbacks to JSON.stringify and handles Map and Set, used for interpolations (e.g. {{ x }}).
If Vue implements this feature, it should reuse that stringifier IMHO.
This, while convenient, is very likely to lead users to get used to code like 'some string' + someRef - not just in logging and debugging, but also in actual code. Without type information and naming conventions, this can make the code more difficult to understand (is this a ref or an actual string?). On the other hand, magic toString is inherently incompatible with type checking and also makes static analysis more difficult.
If you really want it, you can easily wrap computed to attach toString to the ref yourself.
Most helpful comment
@marcusball,
toString()is not available on all types, try type10.toString()into console.Proper way is to use String.
But is worth to check what does transpiled string interpolation. Maybe it does it automatically.
I don't think it is needed at all. Calling
.valueis more consistent with rest of the code. It would be really crazy to have half stuff with.valueand half without it. (even when reactive object already does something similar) and template-compiler transpiles it in view.PS: The value is there because you need to tell to the wrapper, you want to compute the value. (otherwise there is no way to detect when it should run)