Proposal: Boolean.parseBoolean

# Dmitry Soshnikov (8 years ago)

Similar to Number.parseInt, the Boolean.parseBooelan might be useful for "boolean strings" retrieved from some string-based storages, which do not support other types at serialization.

Boolean.parseBoolean('true'); // true
Boolean.parseBoolean('false'); // false

This is to contrast current:

Boolean('false'); // true

In JS people do today:

let shouldRefresh = (data.shouldRefresh === 'true');

Other parsing results:

Boolean.parseBoolean('1'); // true
Boolean.parseBoolean(1); // true
Boolean.parseBoolean(<not-falsey>); // true

Boolean.parseBoolean(true); // true

// Falsey:
Boolean.parseBoolean('0'); // false
Boolean.parseBoolean(''); // false
Boolean.parseBoolean(false); // false

The API, and the results are from Java's corresponding Boolean.parseBoolean method: docs.oracle.com/javase/7/docs/api/java/lang/Boolean.html#parseBoolean(java.lang.String) .

Dmitry

# Ben Newman (8 years ago)

Just to check my understanding, would

Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };

be a reasonable polyfill for your proposed function?

This would definitely be useful for parsing process.env.* environment variables in Node!

Ben

# Dmitry Soshnikov (8 years ago)

On Thu, Mar 16, 2017 at 2:03 PM, Ben Newman <benjamin at cs.stanford.edu>

wrote:

Just to check my understanding, would

Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };

be a reasonable polyfill for your proposed function?

Yep, this looks good.

Dmitry

# Karl Cheng (8 years ago)

On 17 March 2017 at 08:03, Ben Newman <benjamin at cs.stanford.edu> wrote:

Just to check my understanding, would

Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };

be a reasonable polyfill for your proposed function?

Not quite -- that would throw for strings that are not valid JSON, e.g.:

Boolean.parseBoolean('{dddddd]');

It'd probably be more like:

Boolean.parseBoolean = function (val) {
  if (val === 'false') return false;
  return !!val;
};
# 段垚 (8 years ago)

在 2017/3/17 5:03, Ben Newman 写道:

Just to check my understanding, would

Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };

be a reasonable polyfill for your proposed function?

This implemention throws for invalid JSON syntax and is case-sensitive (Java's counterpart is case-insensitive). Is this better?

Boolean.parseBoolean = function (value) {
   return !(!value || /^false$/i.test('' + value));
};

However I'm not sure this is widely useful. If the value is not from JSON, there are a lot of alternatives for 'true|false', e.g. 'yes|no', 'on|off', or 'T|F', and different rules for casing/empty value/invalid syntax. So it's better to do this in users' code.

# Garrett Smith (8 years ago)

The user's code…

Trying to parse "" will also throw with JSON; !!"false " is true; host objects (or whatever they're called now) such as document.all.

Unsubscribing. Not sure why I didn't earlier… I need to stay a code-free user. :-)

# Dmitry Soshnikov (8 years ago)

On Thu, Mar 16, 2017 at 7:04 PM, Karl Cheng <qantas94heavy at gmail.com> wrote:

On 17 March 2017 at 08:03, Ben Newman <benjamin at cs.stanford.edu> wrote:

Just to check my understanding, would

Boolean.parseBoolean = function (value) { return !! (value && JSON.parse(String(value))); };

be a reasonable polyfill for your proposed function?

Not quite -- that would throw for strings that are not valid JSON, e.g.:

Boolean.parseBoolean('{dddddd]');

It'd probably be more like:

Boolean.parseBoolean = function (val) {
  if (val === 'false') return false;
  return !!val;
};

Looks good either (probably worth making case-insensitive).

Dmitry

# Augusto Moura (8 years ago)

What would be the result for Boolean.parseBoolean('undefined') and Boolean.parseBoolean('null')?

# Steve Fink (8 years ago)

On 03/16/2017 09:40 PM, Dmitry Soshnikov wrote:

On Thu, Mar 16, 2017 at 7:04 PM, Karl Cheng <qantas94heavy at gmail.com <mailto:qantas94heavy at gmail.com>> wrote:

On 17 March 2017 at 08:03, Ben Newman <benjamin at cs.stanford.edu
<mailto:benjamin at cs.stanford.edu>> wrote:
> Just to check my understanding, would
>
>   Boolean.parseBoolean = function (value) {
>     return !! (value && JSON.parse(String(value)));
>   };
>
> be a reasonable polyfill for your proposed function?

Not quite -- that would throw for strings that are not valid JSON,
e.g.:

```
Boolean.parseBoolean('{dddddd]');
```

It'd probably be more like:

```
Boolean.parseBoolean = function (val) {
  if (val === 'false') return false;
  return !!val;
};
```

Looks good either (probably worth making case-insensitive).

There are many, many reasonable choices for a function that maps a string to a boolean. Even more for a function that maps an arbitrary value to a boolean. The choice of the function is highly context dependent. That context includes language/locale/whatever the right l10n term is. It's true that JS could arbitrarily pick one, but then it would implicitly be favoring one context over another. And not even Node and the Web would completely agree on the most appropriate definition. It makes sense for JSON to pick a single function, because it's a specified interchange format.

-1 from me.

# Dmitry Soshnikov (8 years ago)

On Fri, Mar 17, 2017 at 7:42 AM Augusto Moura <augusto.borgesm at gmail.com>

wrote:

What would be the result for Boolean.parseBoolean('undefined') and Boolean.parseBoolean('null')?

Perhaps this should be restricted to JSON-compatible "false" only. Other possible may include "", and "0". For stricter handling "null", "undefined", and similar strings may even throw as non-Boolean parseable.

Dmitry

# Dmitry Soshnikov (8 years ago)

On Thu, Mar 16, 2017 at 1:55 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

Similar to Number.parseInt, the Boolean.parseBooelan might be useful for "boolean strings" retrieved from some string-based storages, which do not support other types at serialization.

Boolean.parseBoolean('true'); // true
Boolean.parseBoolean('false'); // false

OK, here the actual proposed spec for it: gist.github.com/DmitrySoshnikov/5ee1a7d51d8dbe159ae917876b27f36a

I made it plain simple (anything which is not case-insensitive "true" is false), and copy-pasted from Java.

Dmitry

# T.J. Crowder (8 years ago)

Any reason for not just using Boolean.parse? (Rather than repeating Boolean in the function name?)

-- T.J. Crowder

# Dmitry Soshnikov (8 years ago)

On Mon, Mar 20, 2017 at 11:57 AM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote:

Any reason for not just using Boolean.parse? (Rather than repeating Boolean in the function name?)

Just a copy-paste from Java, similarly was done with parseInt taken from Java. But just parse probably would work too. For consistency and predictability parseBoolean is probably better now.

Dmitry

# James Treworgy (8 years ago)

I'd say there's no clear model for consistenty, e.g. JSON.parse. One could argue that the template is that anything which has only one way to parse is to use parse. Numbers have more than one way (parseInt, parseFloat)

# kdex (8 years ago)

One could argue that parse makes more sense, as there is really just that one way to parse a bool.

# T.J. Crowder (8 years ago)

Funny, I'd go the other way. We have parseInt in part because we also have parseFloat. Date has parse (but it doesn't return a Date, sigh). JSON has parse.

For me, consistency with Java isn't important for this.

My $0.02 for what it's worth...

-- T.J. Crowder

# Andrea Giammarchi (8 years ago)

As mentioned in the gist, and FWIW, -1 here.

/^true$/i.test(str) works since ever for the specified use case

Boolean.parseBoolean(1) that returns false is a footgun.

Either we talk about a better definition of truthy-like values, or having a public spec about just string type and true as value looks like the solution for 1% of use cases that's also already covered by JSON.parse

# Dmitry Soshnikov (8 years ago)

On Mon, Mar 20, 2017 at 12:09 PM, kdex <kdex at kdex.de> wrote:

One could argue that parse makes more sense, as there is really just that one way to parse a bool.

I agree, just parse sounds good (similar to Date.parse, and JSON.parse). Since in parseInt, the Int is a quantifier.

Dmitry

# Dmitry Soshnikov (8 years ago)

On Mon, Mar 20, 2017 at 12:12 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:

As mentioned in the gist, and FWIW, -1 here.

/^true$/i.test(str) works since ever for the specified use case

Boolean.parseBoolean(1) that returns false is a footgun.

Either we talk about a better definition of truthy-like values, or having a public spec about just string type and true as value looks like the solution for 1% of use cases that's also already covered by JSON.parse

Still, semantics matter :) With a JSON.parse you may parse any JSON value, and then will have to do extra checks. RegExp test is also less semantic. Initially in the thread I considered truthy/falsey values, but then reduced to strings only, and took Java's implementation, but this can be discussed. The need for a semantic method from Boolean still exists, instead of using ad-hoc technics like JSON or regexp, which are just implementation details for the semantic method.

Dmitry

# Andrea Giammarchi (8 years ago)

I still think Boolean.parse makes sense only if gives us something more than JSON.parse like /^true|yes|y|1$/i.test(value) would do.

Otherwise I personally don't see any real-world use case for it, specially not those from bash or env variables.

# Michael J. Ryan (8 years ago)

I would add case insensitive "t", "y", "yes", 1, -1 as well

# Michael J. Ryan (8 years ago)

My suggestion for a polyfill.

if (!Boolean.parse) { Boolean.parse = function(input) { // return false if it is already falsy if (!input) return false;

var expr = String(input);

// return false if it's reasonably too long of a string
if (expr.length > 10) return false;

// test trimmed input against truthy values
return (/^(-?1|y|t|yes|true)$/).test(expr.trim().toLowerCase());

} }

-1/1 are common database boolean/bit fields y/yes also common inputs for truthiness t/true also common for truthiness

These account for pretty much every case of truthy stored values I've seen in the wild.

--- Dmitry, sorry, meant to reply-all the first time, also refactored the polyfill slightly to better account for potentially too long an input value.

# Dmitry Soshnikov (8 years ago)

On Mon, Mar 20, 2017 at 4:59 PM, Michael J. Ryan <tracker1 at gmail.com> wrote:

My suggestion for a polyfill.

if (!Boolean.parse) { Boolean.parse = function(input) { // return false if it is already falsy if (!input) return false;

var expr = String(input);

// return false if it's reasonably too long of a string
if (expr.length > 10) return false;

// test trimmed input against truthy values
return (/^(-?1|y|t|yes|true)$/).test(expr.trim().toLowerCase());

} }

-1/1 are common database boolean/bit fields y/yes also common inputs for truthiness t/true also common for truthiness

Yeah, these might be good in general, although I'd like to reduce the proposal to minimum vital version, and JS related. The problem we are trying to solve is to parse "false" as false. It's not possible with Boolean('false') today. And all the JSON.parse, and regexp manipulations are too low-lever implementation details; users want good semantic library! :)

So:

Boolean.parse('true'); // true
Boolean.parse('false'); // false

That's all we need for now, and already will be much better semantic alternative too all existing "non-semantic building material".

Dmitry

# Michael J. Ryan (8 years ago)

I slightly disagree... mainly in that as it stands, we have a fairly loose type coercion system that allows almost anything to be coerced into a boolean... in this case "parse" at least in my mind means that it should cover the most common use cases. I understand that Boolean("false") doesn't currently work this way, and why Date.parse doesn't give a date instance is a bit beyond me.

With my suggested polyfill your use case would work as expected... However, JS interacts with more than just serialized results from JS. It interacts with input from multiple systems, sources, users and good/bad the content of users. The type coercion as it exists for boolean is in order to provide for simplistic validation... why an empty string coerces false, for example. Much like we have defined "falsey" values in JS, I think that Boolean.parse should have common truthy values/strings that can predictably be converted as a true, where all else is false.

If all it does is:

input => String(input).toLowerCase() === 'true';

what is the point of extending Boolean?

# Dmitry Soshnikov (8 years ago)

On Tue, Mar 21, 2017 at 11:49 AM, Michael J. Ryan <tracker1 at gmail.com>

wrote:

I slightly disagree... mainly in that as it stands, we have a fairly loose type coercion system that allows almost anything to be coerced into a boolean... in this case "parse" at least in my mind means that it should cover the most common use cases. I understand that Boolean("false") doesn't currently work this way, and why Date.parse doesn't give a date instance is a bit beyond me.

With my suggested polyfill your use case would work as expected... However, JS interacts with more than just serialized results from JS. It interacts with input from multiple systems, sources, users and good/bad the content of users. The type coercion as it exists for boolean is in order to provide for simplistic validation... why an empty string coerces false, for example. Much like we have defined "falsey" values in JS, I think that Boolean.parse should have common truthy values/strings that can predictably be converted as a true, where all else is false.

If all it does is:

input => String(input).toLowerCase() === 'true';

what is the point of extending Boolean?

Yeah, all good points, but they open a door for more questions mentioned above (so many different formats, "yes", "1", "on", etc, and "why one, but not another?", and "why not i18n?").

So to reduce this, having a good MVP would be good. Then, if there is a need, it can be extended by adding.

The actual practical use-case I want to solve is:

  • Not to use "raw building material" (aka "syntactic garbage") to solve the issue. With this I mean using non-semantic techniques to achieve the goal, like RegExp testings, JSON.parsing, etc. This is also a building material: "String(input).toLowerCase() === 'true';", and users want nice semantic library.

  • To solve Boolean('false') issue. This is an actual use-case I had, when was asked why Boolean type coercion treats "false" as true, and there is no good answer other than -- "it's specified so". So to keep backward compats we need Boolean.parse(...) for this.

So the only question it needs to address whether we accept truthy/false values, or only strings.

Dmitry

# Jordan Harband (8 years ago)

The good answer is that Boolean(x) is the same as ‼x (which is a good thing) - and the string "false" is truthy, since the only falsy string value is the empty string.