Skip to content

Nullish coalescing operator (??) #26578

Closed

Description

@samclaus

Search Terms

  • nullish coalescing

Suggestion

A nullish coalescing operator, which is essentially an alternative to || that will only return the right-side expression if the left-side is null or undefined (|| returns the right-side if the left-side is falsy, i.e. null | undefined | "" | 0 | false | NaN).

Use Cases

This would be extremely useful anywhere where defaults are needed for potentially omitted inputs, but empty strings or 0, and so forth, are valid inputs that shouldn't be defaulted. My particular use case is AngularJS component bindings. Whenever bindings are updated, I would like to provide a default for a string or boolean binding only when they are straight up omitted (undefined), but I have to do a full-fledged ternary expression with typeof to handle the falsy input corner-case.

In conjunction with the safe chaining operator (#16), handling optionals would be trivial.

Examples

export interface Configuration {
    // Default: "(no name)"; empty string IS valid
    name?:  string;

    // Default: -1; 0 is valid
    items?:  number;

    // Default: true
    active?: boolean;
}

function configureSomething(config: Configuration) {
    // With null-coalescing operator
    config.name = config.name ?? "(no name)";
    config.items = config.items ?? -1;
    config.active = config.active ?? true;

    // Current solution
    config.name = typeof config.name === "string" ? config.name : "(no name)";
    config.items = typeof config.items === "number" ? config.items : -1;
    config.active = typeof config.active === "boolean" ? config.active : true;

    // Using || operator (INCORRECT)
    config.name = config.name || "(no name)"; // does not allow for "" input
    config.items = config.items || -1; // does not allow for 0 input
    config.active = config.active || true; // really bad, always true
}

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)

Activity

  1. ghost added
    Out of ScopeThis idea sits outside of the TypeScript language design constraints
    on Aug 21, 2018
  2. jhpratt commented on Dec 9, 2018

    @jhpratt

    Andy (Andrewkraft) (@Andy-MS) Shouldn't the tag be waiting for TC39, not out of scope?

  3. MatthiasKunnen commented on Jun 10, 2019

    @MatthiasKunnen

    Nullish coalescing has reached stage 2. Can this issue be reopened or will this be addressed elsewhere?

  4. davidje13 commented on Jul 7, 2019

    @davidje13

    Matthias Kunnen (@MatthiasKunnen) given the close connection, I'm guessing this will be brought in along with #16, but the general rule seems to be to wait for stage 3, so we have a bit longer to wait yet.

  5. added
    Waiting for TC39Unactionable until TC39 reaches some conclusion
    and removed
    Out of ScopeThis idea sits outside of the TypeScript language design constraints
    on Jul 15, 2019
  6. natew commented on Jul 24, 2019

    @natew

    Stage 3 now!

  7. jhpratt commented on Jul 24, 2019

    @jhpratt
  8. DanielRosenwasser commented on Jul 24, 2019

    @DanielRosenwasser
    Member

    You're welcome!

  9. Kingwl commented on Jul 24, 2019

    @Kingwl
    Contributor

    Could i take a try on this?

  10. DanielRosenwasser commented on Jul 24, 2019

    @DanielRosenwasser
    Member

    Ron Buckton (@rbuckton) has an old branch that implements this (I would link you to it but it's searchable and I'm on mobile), so it depends on how bad the merge conflict would be and whether he would mind.

  11. 12 remaining items

  12. rbuckton commented on Aug 4, 2019

    @rbuckton
    Contributor
  13. RyanCavanaugh commented on Aug 14, 2019

    @RyanCavanaugh
    Member

    Hey folks (in particular Wenlu Wang (@Kingwl) and Titian Cernicova-Dragomir (@dragomirtitian)) - we'd love to have this feature shipped as a headlining "community-implemented" feature in 3.7. I think whoever claims dibs first can put up a draft PR and then hopefully work with others to contribute fixes, finish things out, and add testcases.

    Sheetal Nandi (@sheetalkamat) will be helping coordinate and offer advice / code review throughout the process.

    Thanks!

  14. dragomirtitian commented on Aug 14, 2019

    @dragomirtitian
    Contributor

    Ryan Cavanaugh (@RyanCavanaugh) Hey, I have a 6 day chunk of time free time starting tomorrow, so I can start on this right away.

    Sheetal Nandi (@sheetalkamat) Should I start from Ron Buckton (@rbuckton) 's old branch? Or should I start from scratch?

    Thanks!

  15. Kingwl commented on Aug 14, 2019

    @Kingwl
    Contributor

    Titian Cernicova-Dragomir (@dragomirtitian)
    I already have a migrated branch, based Ron Buckton (@rbuckton) commit (and a few changes). Could we work on it?🤔

  16. dragomirtitian commented on Aug 14, 2019

    @dragomirtitian
    Contributor

    Wenlu Wang (@Kingwl) Hi, sure, I'd be happy to collaborate on what is already there. Are you on gitter ? Maybe we can sync there as to what work still needs to be done and how to divide it up.

  17. Kingwl commented on Aug 14, 2019

    @Kingwl
    Contributor

    Titian Cernicova-Dragomir (@dragomirtitian) Sure, Thanks
    Fortunately, I'm at UTC+8 and you are at UTC+3😍

  18. nisimjoseph commented on Oct 15, 2019

    @nisimjoseph
  19. DanielRosenwasser commented on Oct 15, 2019

    @DanielRosenwasser
    Member

    You're welcome! If you would like to suggest improvements, feel free to open another issue.

  20. the21st commented on Feb 18, 2020

    @the21st

    What about the question raised by Anders Lassen (@Duckers) ? I'm curious what's the recommended syntax there. Is there a plan to add safe coalescing operator to replace && ?

  21. samhh commented on Feb 18, 2020

    @samhh

    Simon Sotak Gregor (@the21st) This is a more appropriate question for TC39, perhaps here.

  22. dantonel commented on Jun 2, 2020

    @dantonel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions