React only checks references but since the objects aren't immutable they could have changed even without the reference changing.
Immutability also has a performance price which is not always great.
I know this gets into a complex land of computer science that I don’t understand well, but I wish I could define in TypeScript “any object passed into this function is now typed _never_. You’ve destroyed it and can’t use it after this.” Because I sometimes want to mutate something in a function and return it for convenience and performance reasons, but I want you to have to reason about the returned type and never again touch the original type, even if they are the same object.
For example:
# Original array
array = [1, 2, 3]
# Using map (non-destructive)
new_array = array.map { |x| x * 2 }
# new_array is [2, 4, 6]
# array is still [1, 2, 3] (unchanged)
# Using map! (destructive)
array.map! { |x| x * 2 }
# array is now [2, 4, 6] (modified in-place)
Is the keyword. Anything that should never be broken isn’t a convention. There’s no better convention than compiler error.
If you don't want an object mutated in Ruby, you can freeze it.
https://www.typescriptlang.org/play/?#code/C4TwDgpgBAYg9nKBe...
1. You cannot return anything (say an immutable result that has consumed the input)
Okay, so don't return anything, just mutate the original. Except:
2. You cannot mutate the original, return nothing, but the mutated original isn't a subset of the original. For example: https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABB...
Having explicit language to differentiate between pass by reference and pass by value avoids this confusion. It requires a little more thought from the programmer but it’s really minimal once you internalize it.
Rust takes this a step further with an explicit ownership and borrowing model. The compiler will refuse your code if you try to write something that that violates the borrow checker. This is endlessly frustrating to beginners but after adapting your mind to ownership safety you find yourself thinking in the same way in other languages.
I always found real-world JavaScript codebases frustrating because there was so much sharing that wasn’t entirely intentionally. It only got fixed when someone recognized a bug as a result.
Outlook at that issue even in their old C++ (I think) version.
You're in London, you save your friend's birthday as March 11th.
You're now in SF. When is your friend's birthday? It's still all-day March 11th, not March 10th, starting at 5PM, and ending March 11th at 5PM.
A lot of that gets back to why Temporal adds so many different types, because there are different uses for time zone information and being clear how you shift that information can make a big difference. (A birthday is a PlainDate at rest, but when it is time to send them an ecard you want the ZonedDateTime of the recipient's time zone to find the best time to send it.)
What I don't understand is why they had to make string formatting so rigid. Maybe it has to do with internationalization? I'd have liked if it included a sort of templating system to make the construction of rendered date-time strings much easier.
Congrats to all the champions who worked super hard on this for so long! It's been fun working on temporal_rs for the last couple years :)
Given that the article refers to the "radical proposal" to bring these features to JavaScript came in 2018, surely Java's own solutions had some influence?
Safari confirmed as IE Spiritual successor in 2020+.
Date is out, Temporal is in
I didn't spot how Temporal fixes this. What happens when "now" changes? Does the library get updated and pushed out rapidly via browsers?
This is not the case for Temporal objects. Also, the temporal objects have functions on them, which, granted, makes it convenient to use, but a pain to pass it over the wire.
I'd clearly prefer a set of pure functions, into which I can pass data-only temporal objects, quite a bit like date-fns did it.
For example `JSON.parse(JSON.stringify(Temporal.PlainYearMonth.from({year:2026,month:1}))).subtract({ years: 1})` won't work, because it misses the prototype and is no longer an instance of Temporal.PlainYearMonth.
This is problematic if you use tRPC for example.
If not, that regardless of being plain data or a serialized object with functions, you'd still need to convert it to the type you want.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
That said, I think the Temporal team made the right call here. Date-time logic is one of those domains where the "bag of data plus free functions" approach leads to subtle bugs because callers forget to pass the right context (calendar system, timezone) to the right function. Binding the operations to the object means the type system can enforce that a PlainDate never accidentally gets treated as a ZonedDateTime. date-fns is great but it can't give you that.
The serialization issue is solvable at the boundary. If you're using tRPC or similar, a thin transform layer that calls Temporal.Whatever.from() on the way in and .toString() on the way out is pretty minimal overhead. Same pattern people use with Decimal types or any value object that doesn't roundtrip through JSON natively. Annoying, sure, but the alternative is giving up the type safety that makes the API worth having in the first place.
The real drawback of the functional approach is UX, because it's harder to code and you don't get nice auto-complete.
But I'd easily pay that price.
const now = new Date();
The Temporal equivalent is: const now = Temporal.Now.zonedDateTimeISO();
Dear god, that's so much uglier!I mean, I guess it's two steps forward and one step back ... but couldn't they have come up with something that was just two steps forward, and none back ... instead of making us write this nightmare all over the place?
Why not?
const now = DateTime();Outside of scheduling UTC is the way.
It's weird that they picked example code that is extremely non-accidentally doing this.
This is funny to me; Java's util.Date was almost certainly a port of C's time.h API!
jon_kuperman•2h ago