Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional assignment that creates keys if they dont exist #6

Open
lilnasy opened this issue Jul 17, 2023 · 6 comments
Open

Optional assignment that creates keys if they dont exist #6

lilnasy opened this issue Jul 17, 2023 · 6 comments

Comments

@lilnasy
Copy link

lilnasy commented Jul 17, 2023

I'm curious if the following pattern is something this proposal will consider within scope.

// An object containing optimized urls for `imageSrc` in various formats and resolutions
const manifest = {}

manifest[imageSrc]              ??= {}
manifest[imageSrc][format]      ??= {}
manifest[imageSrc][format][width] = url

Relevant: lodash's utility:

_.setWith(manifest, '[${imageSrc}][${format}][${width}]', url)
@zaygraveyard
Copy link

I don't believe it is, and your example can be one-lined today (if that what you're after) as follows:

// An object containing optimized urls for `imageSrc` in various formats and resolutions
const manifest = {}

((manifest[imageSrc] ??= {})[format] ??= {})[width] = url

@ChristianMayer
Copy link

I want to support this proposal and with this issue included.

Use case is an object with an optional value of type object. As a simple example:

var circle = {r: 1, color: {r: 1, g: 1, b:1}};     // might optionally have "meta" of type object
...
function show(c) {
  ...
  c.meta?.showing = true;
}

Right now the line must be instead e.g. (c.meta ??= {}).showing = true - something that's looking very clumsy.

So my enhancement proposal is that a left hand use (i.e. assignment) of an optional chaining does silently create an empty object. So that

object.optional?.property = value;

is a short cut for

(object.optional ??= {}).property = value;

@zaygraveyard
Copy link

@ChristianMayer I disagree with your suggestion. As IMHO, it would imply too much magic.
But that's just my opinion, which might not matter much 😅.

@Patrick-ring-motive
Copy link

This gives me a decent idea for an alternative to the main use case. I'm sure others have found this before but I like it.

(expr1??{}).prop = val

Not as memory efficient but more DRY and readable than

expr1 == null ? undefined : expr1.prop = val

@samueldcorbin
Copy link

samueldcorbin commented Jun 27, 2024

Creating simple intermediate structure when it doesn't exist is a pretty common JS annoyance, and that was what I was assuming this proposal was at first (that is, I found it while looking to see if there was a proposal to solve that problem).

Using the return from ??= works, but gets pretty unreadable if you're poking a property into something more deeply nested, and doing this with a library usually involves string overhead.

Short-circuiting the assignment when it doesn't exist seems very useful too though.

It's too bad typescript makes use of !. unviable. It'd be nice if you could have something like:
outer?.inner?.evenMoreInner?.property = value as the short-circuit assignment
outer.inner!.evenMoreInner!.property = value as an assignment that creates intermediate simple objects if necessary

@drpicox
Copy link

drpicox commented Sep 10, 2024

But the autocreation of fields and objects with ?. is dangerous, and really unexpected. We do not expect that behavior from the right side of the equals, so I would not expect that from the left side. Maybe a different proposal with a different syntax. Btw... I think that !. is used by Typescript to ensure that they are not null, so do not throw a compile error.

Example: https://www.typescriptlang.org/play/?#code/C4TwDgpgBAglC8UDeAoK6oEMD8AuZUAxvgM7ABOAlgHYDmUAvgDQoMooA2EwW+ciSBlhJZqIANwpMAOkwBCaYQRQA5AAtKK8VAD0OqJR6EA9gFswlLiSmzFy9Zu16DPACbGII6saNmLXIA

type A = {
    a?: { c: string };
}:

let a: A = {} as any;
a.a!.c = 'hi'; // it compiles
a.a.c = 'hi'; // it does not compile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants