Consistent String-to-Boolean Conversion Method

Introduction: The current behavior of the Boolean() constructor in JavaScript does not consistently interpret string data in line with its toString() method. This inconsistency causes unforeseen behavior and requires developers to use ad-hoc workarounds. The proposal suggests the addition of a new function, either Boolean.fromString() or Boolean.parse(), to rectify this long-standing issue.

Existing Behavior: The current behavior of Boolean conversion in JavaScript shows discrepancies, as demonstrated by the following examples:

console.log(Boolean()); // Outputs: false
console.log(Boolean(Boolean().toString())); // Outputs: true

console.log(Boolean('false')); // Outputs: true
console.log(Boolean('true')); // Outputs: true

console.log(Boolean('0')); // Outputs: true
console.log(Boolean(0)); // Outputs: false

console.log(Boolean(0)); // Outputs: false
console.log(Boolean(Boolean(0).toString())); // Outputs: true

Developer Pain Points: The inconsistency in Boolean conversion leads to developers using makeshift solutions, resulting in complex, error-prone code to handle string-to-Boolean conversion. For instance:

javascript

function proBool(value) {
    if (typeof value === "string" && (value.toLowerCase() === "false" || value === "0")) {
        return false;
    }
    if (typeof value === "number" && value === 0) {
        return false;
    }
    return Boolean(value);
}

Moreover, reputable projects like Babel have incorporated similar workarounds to maintain consistency in Boolean interpretation.
Babel Github

Use Cases: The need for consistent string-to-Boolean conversion arises in various scenarios, including but not limited to:

  • Processing serialized data
  • Handling non-BSON database structures
  • Dealing with aggregated strings
  • Parsing command-line interface (CLI) input
  • Parsing serialized data streams

Proposal: Introduce a new method, such as Boolean.fromString() or Boolean.parse(), to offer a standardized approach to convert strings into Booleans. This proposed method should provide consistent behavior, aligning with developer expectations and reducing the need for workaround functions.

Expected Impact: By standardizing the string-to-Boolean conversion method, we anticipate reduced complexity in codebases, improved code readability, and enhanced overall reliability in JavaScript applications.

Conclusion: Addressing the longstanding inconsistency in Boolean conversion, will significantly enhance the JavaScript language. Introducing a standardized method for string-to-Boolean conversion, whether through the addition of a new function or by updating the existing Boolean() constructor, holds the potential to streamline development practices.

While an alteration to the core behavior of Boolean() might appear to be a breaking change, its widespread use as a fallback in numerous scenarios implies that the potential side effects of an update could be minimal or negligible. The benefits of aligning JavaScript's Boolean behavior with developer expectations and standards far outweigh the potential short-term adjustments.

This proposal aims to modernize a critical part of JavaScript, refining its behavior and ensuring consistency in handling string-to-Boolean conversions. Your consideration and support for this improvement to the JavaScript language are highly valued.

Your thoughts and feedback on this proposal are highly appreciated. Thank you for considering this enhancement to the JavaScript language.

Hi!

I would argue that those are 5 different scenarios, which should not - and cannot - be all handled by a single new method. Really, each of those cases has its own rules for parsing boolean values, which depend on the context.

For example, when parsing CLI arguments or YAML, you would want to ignore case and also treat Yes/No and On/Off as valid inputs (besides True/False). Or when handling database structures or data streams, the input often is not even a string but rather a binary representation.

I think the language already has all the tools you need:

  • when serialising using String(bool), bool.toString() or JSON.stringify(bool), use JSON.parse(str) to convert the output back to a boolean
  • when serialising using Number(bool) or +bool, use Boolean(num) or !!num to convert the output back to a boolean

When serialising using a different method to a different, ad-hoc format, you also will need to use your own parsing method.

2 Likes

This also can come up when parsing query strings; Rails has something like it.

However, the logic is so trivial, and as pointed out, so use-case-specific, I'm not sure why it's a hardship to make your own function for it?

Thank you for your input, While crafting custom solutions for specific use cases is possible, the proposal aims to standardize the string-to-Boolean conversion process in JavaScript. This enhancement intends to provide a universally accepted method, fostering consistency across diverse projects and simplifying code, rather than relying on individual workarounds.

It's worth considering at least a standardization where 'false' is universally recognized as false, ensuring a more intuitive and consistent approach to string-to-Boolean conversion. By incorporating a native solution, developers can benefit from a shared understanding and predictable behavior.

Your consideration of this proposal to improve JavaScript's functionality is greatly appreciated.

another example of de/serialization handlers in place
please note how easy it is to serialize a Boolean vs creating the value again

function proBool(value) {
    if (typeof value === "string" && (value.toLowerCase() === "false" || value === "0")) {
        return false;
    }
    if (typeof value === "number" && value === 0) {
        return false;
    }
    return Boolean(value);
}
export class FlakeHandler {
    static serialize(t: Flake) {
        return [t.ID, t.name, t.mod].join('|');
    }
    static hydrate(t: string) {
        const d = t.split('|');
        return { ID: d[0], name: d[1], mod: proBool(d[2]) } as unknown as Flake;
    }
}

The necessity for these custom functions, as demonstrated in the example above, highlights the frequent need to handle string-to-Boolean conversions for serialization and deserialization. While developers can create ad-hoc methods, the error-prone nature of this approach could lead to oversights and unexpected behavior.

I think the problem here is that it's not universally considered a good idea to accept multiple of these kind of inputs - certainly you often need to choose some kind of string representation, but sometimes it's just 1/0, or sometimes it's a specific enum or structure - but having more than one way to say true or false seems like a bad idea. Standardizing that wouldn't be an improvement.

Adding something to the language is costly, and frequency isn't the sole rubric - if it's frequently done, but it's trivial to do it correctly and performantly, the benefit from adding it is often minimal.

2 Likes

Standardizing the interpretation of at least some common string representations, such as 'false', could enhance code consistency without mandating a multitude of representations. This would serve as a foundational framework for handling Boolean values in various contexts, preserving flexibility without compromising clarity or performance.

Your perspective is crucial to this discussion on improving JavaScript, and your considerations are greatly appreciated.

I doubt you'll find a method that will be universally accepted - the requirements are just too diverse for the different use cases.
I'm not even quite sure from reading your posts what that method should be - is the proBool implementation you've shared just an example, or are you proposing it as the universal method?

As shown, that already exists: JSON.parse.

JSON.parse only handles valid JSON objects, are you suggesting all data be preformatted as a JSON string?
in the case of data aggregation or CSV's this is not a valid approach

Everything I have shared is purely an example and how flawed the logic is.

ultimately, Boolean consumes a string value, and cannot consume the output string value. yet it defaults to true unless special cases are involved.

The only logic to not change this is because of 25 year old practices of another language
and that it maybe breaking when users have already implemented their own hot-fixes as a wrapper, which falls back onto the Boolean constructor.
the only case I am concerned about is supporting case insensitivity for 'false' and 'true' on the boolean constructor.

but with that, I am not opposed to supporting other boolean formats such as 0 and "0" for false.
I do think it would be healthy to evaluate all conditions that actually do result in false for a boolean and conclude if its sufficient in the modern environment.

No, JSON.parse handles any valid JSON data, including booleans directly. See JSON.parse('false') === false.

The Boolean constructor doesn't seem broken to me. Its purpose isn't to convert strings to booleans, rather, it's to convert truthy to true and falsey to false. I don't know if any language where the string 'true' is considered "truthy" (if such a language does exist, I'd feel sorry for that design choice). If the Boolean constructor were to change meaning, and if it were to suddenly start returning true when given '1' or 'true', then it's not a truthy/falsey converter anymore, and a lot of code I've written in the past would certainly break.

Check out JSON.parse() as above
Boolean('true') already returns a true value
Boolean('false') also returns true.
yet Boolean('') returns false.

at surface level, Boolean() appears to use string.length>0

Yes, exactly - a "truthy" string is one that has content, and a "falsey" string is one that doesn't. The content of the string doesn't matter when dealing with truthy/falsey.

The Boolean constructor behaves exactly the same as "if" in the language.

if ('true') console.log('this will run');
if ('false') console.log('this will still run');
if ('') console.log('this will not run');

This is why I'm proposing a .fromString() or .parse() method
so we don't need to break 20 year old code practices.

for validity in this issue, you can find millions of results dating back to 2010 where Boolean has been mishandled and users simply rely on buggy and convoluted alternatives.
~17,200,000 results according to Google

so, why can't we just add it or borrow code from JSON.parse() to make it clear for users?

to look at the counter point of falsly and truthly, then .toString() does not return a falsly equivalent string

Just curious - what did you Google?

As for how a .fromString() method should behave - I tend to agree with others that this seems to be highly context sensitive. If JavaScript were to provide a native one, I hope that it's simply just the following:

Boolean.fromString = function (value) {
  if (value === 'true') {
    return true;
  } else if (value === 'false') {
    return false;
  } else {
    throw new TypeError('Invalid value');
  }
}

If it were implemented like that, then I could use it in a handful of places, such as with query parameters and what-not. If we start adding support for treating 1 as true and 0 as false, then the function would become useless to me - I can't think of a time when I've wanted an implementation to be exactly like that. Same with case sensitivity - I'd prefer it to care that the letters were lowercased - if I wanted it to be case insensitive, I could do .toLowerCase() myself. It really doesn't matter if JavaScript considers the strings "1" and "true" to be equivalent to the value true via this new standard method, because these strings will be coming from different sources (YAML, user input, query parameters) that have different expectations with them that are unrelated to JavaScript.

and I agree with this 100%.
as for the search query: why does boolean return true on "false" javascript

I tried the google search out - the first result seemed mostly relevant (though they were attempting to use new Boolean(), not just Boolean() - and were basically stating it as "something they tried" as opposed to "I have this weird bug"). The next 9 results were completely irrelevant. I stopped looking after that - I assume the results just get less and less relevant. So, no I wasn't really able to find millions of instances of buggy code or Boolean being mishandled.

Not to say that this doesn't cause bugs. People are always misunderstanding how APIs work and are misusing them, so I'm sure there's many cases where bugs came about because people didn't check what Boolean() did before using it.