Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Request to add: unreachable #21

Closed
Jack-Works opened this issue Oct 29, 2021 · 10 comments
Closed

Request to add: unreachable #21

Jack-Works opened this issue Oct 29, 2021 · 10 comments
Labels
enhancement New feature or request

Comments

@Jack-Works
Copy link
Member

Jack-Works commented Oct 29, 2021

Implementation: (maybe Function.unreachable)

function unreachable(_val) {
    throw new TypeError()
}

Usage:

function route(direction) {
    switch (direction) {
        case "up": case "down": return "left";
        case "left": case "right": return "up";
        default: Function.unreachable(direction)
    }
}

The real power of this helper is used with TypeScript. This function should have type signature (val: never) => never

type Direction = 'up' | 'down' | 'left' | 'right'
function route(direction: Direction) {
    switch (direction) {
        case "up": case "down": return "left";
        case "left": case "right": return "up";
        default: Function.unreachable(direction)
    }
}

It will provide an exhaustive matching guard, which means if I'm missing some cases, it will become a compile error.

Let's say I add one new direction to the type Direction

type Direction = 'up' | 'down' | 'left' | 'right' | 'stay'

image

The compiler will tell me that: hey! direction is no longer type never (when you exhaustive all possibilities of a variable), you still have one case to check!

This unreachable function is very useful and I have implemented it in many of my repos.

@ljharb
Copy link
Member

ljharb commented Oct 29, 2021

What would be the use case for this in JS?

@jridgewell
Copy link
Member

I've used this before when doing exhaustive switch statements (like the OP). It's also common in iterations that never cease:

function ex() {
  while (true) {
    if (someCondition()) return;
  }

  throw new TypeError('unreachable');
}

More common in C++ code, because the type has to be proven, but I've done the exact same in JS.

@ljharb
Copy link
Member

ljharb commented Oct 29, 2021

so this is basically "expose %ThrowTypeError%, but with a customized error message about unreachability"?

@Jack-Works
Copy link
Member Author

so this is basically "expose %ThrowTypeError%, but with a customized error message about unreachability"?

There is a value passed in, so I think it's clear about what variable is not exhaustive matched and where it happened.

@ljharb
Copy link
Member

ljharb commented Oct 30, 2021

Why would you pass a value in, and why always only one? If it’s unreachable, you aren’t using the value anyways.

@jridgewell
Copy link
Member

jridgewell commented Oct 30, 2021

See the TS example in OP. By passing a parameter, typescript will warn while type checking. Our actual 262 need not have a parameter, but if TS defines one and gives it a never type, it gives an extremely pleasant dev experience.

@ljharb
Copy link
Member

ljharb commented Oct 30, 2021

This seems like it’d be better handled by some kind of TS-only syntax, rather than adding something to JS.

@js-choi js-choi assigned ljharb and unassigned ljharb Oct 30, 2021
@js-choi js-choi added the enhancement New feature or request label Oct 30, 2021
@js-choi
Copy link
Collaborator

js-choi commented Oct 30, 2021

Thanks for opening this issue. This would need to be proposed as a separate proposal, since I am splitting this proposal up as per the most recent plenary’s feedback (#17 (comment)).

I see an analogy between this function and “never”/“nothing” parsers in parser-combinator libraries, which intrigues me a little.

But I don’t really see any use cases other than static checking external to JavaScript itself. Would it always throw a TypeError with a blank message? Is there no way to make it more generally useful? These are issues that I would ask before I would wish to present this, and I would be tackling other helper functions before this anyway.

Of course, any Committee delegate or expert is free to independently propose this function themselves. Either way, it’d need to have its own proposal.

Hopefully that all makes sense! 😄

@Jack-Works
Copy link
Member Author

Why would you pass a value in, and why always only one? If it’s unreachable, you aren’t using the value anyways.

No, when you forgot to handle some possibility, it will halt the program at runtime instead of making the program into a bad state.

@js-choi
Copy link
Collaborator

js-choi commented Nov 11, 2021

Like I mentioned in #21 (comment), this unreachable function would need to be a separate proposal. I will not be able to create and champion such a separate proposal for this function, mostly due to limited bandwidth. If you’re interested, I encourage you to create your own proposal! : )

@js-choi js-choi closed this as completed Nov 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants