Safe Assignment Operator

This week i wrote a draft proposal which got a lot of attention and support for the community (specially on X):

It follows some aspects of a previously discussed topic here but with some different ideas and is a little bit more specified.

It basically tries to port the idea as error as values from Go/rust/... to JS

This is the syntax that I proposed (alongside with Symbol.result)

const [error, response] ?= await fetch("https://arthur.place")

However there is a pending vote in which syntax would be preferred as well as a lot of things that obviously would improve the proposal in general.

I know this was already discussed here but the "major mentality" JS of devs in 2024 (if I can even say that) is evolving towards a more safe approach. As we can observe with recent type stripping proposal and feature flag on nodejs, which 5-10 years ago the same proposal would've been instantly closed.

With all that said, I would like the opinion of this forum as well if I there's any champion that would like to support me with it.

Regards,
Arthur Fiorette

1 Like

Why is a protocol desirable? This seems like if it’s anything but sugar for a try/catch, it’d be confusing.

Yes I find the coupling to assignment strange. The OG proposal suggested better syntax imo:

const [err, data] = try foo()

Which has the advantage of being more intuitive, vs arbitrary punctuation, and being usable as a side effect (basically like catch {})

try foo()
1 Like

Hi @arthurfiorette, welcome!

The Symbol.result reminds me a little of GitHub - tc39/proposal-extractors: Extractors for ECMAScript have you looked into that proposal?

1 Like

Worded like that, it won't work. A function is an object. You cannot define safe assignment as acting on a value on the right-hand side. You only get a value if there was no error.

Your first example evaluates the right-hand side, then calls its [Symbol.result]

What would the following do?

function fun(a, b) { return a / b }

const [e, v] ?= action

Your second example shows a new way of evaluating a function-call expression:

Which could work, but you're allowing any error -- that happens before the function gets invoked -- to escape. And you'd also need a way to pass this through.

[e, v] ?= x.y.m(a, b.c.d, f())

You cannot call this safe assignment, when it can blow up in 5 other places before the method gets called.

In the end you'll realize that previous attempts at try-expression or the like are much more well-rounded -- they don't have any of these pitfalls and can be used anywhere, not just in assignment and variable declarations.

Why assignment is necessary to "try" something, meaning ignoring the error in some cases. I like the try keyword as it was proposed back then in 2019. E.g. try something() where I don't care about return value or error. I just want this line not to throw so my program continues

2 Likes

Hey guys I implemented try-expression assignment yesterday.

Key points

  • try-expression are converted into try-catch with possible finally block
  • ! operator at the end of the expression indicates return the captured Error,
    otherwise will return null;
  • ?? operator after the expression will be taken as fallback value in catch and finaly blocks
  • can be used in variable declaration lists

Example

Here's the playground implementation

I like the idea of using both try keyword or ?= operator, anyways ?= can have even more benefits, since there is no way to have an error of using try await fn() or await try fn() which will definitely break ESLint, Babel and Typescript.

About using

try foo()

While it has benefits, I have no such constructions in my code, it almost never happens, and better to check for an error, this is definitely a good practice.

Why is a protocol desirable? This seems like if it’s anything but sugar for a try/catch, it’d be confusing.

This makes less code, less scopes, easier to read in a similar to await way, so yes it is sugar, it adds ability to write less code in a linear way.

By the way, both variants try and ?= are supported by Goldstein.