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

Suggestion: --noImplicitBooleanConversion #9702

Closed
buola opened this issue Jul 13, 2016 · 2 comments
Closed

Suggestion: --noImplicitBooleanConversion #9702

buola opened this issue Jul 13, 2016 · 2 comments
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript

Comments

@buola
Copy link

buola commented Jul 13, 2016

Typescript forbids automatic conversion to boolean in function calls, which makes sense, since there's actually no coercion in the generated typescript code when passing a non-boolean argument to a function taking a boolean. The Javascript function would receive a non-boolean.

However, it allows coercion to boolean in 'if', 'while', 'for' and 'operator !'

This can lead to hard-to-find bugs, such as:

//Prints number and/or array, when given
function f(n?: number, a?: number[]) {
  if(n) console.log(n); //there is a bug here, should be if(n!==undefined)
  if(a) console.log(a); //this is okay
}

f(1); //prints 1
f(1, []); //prints 1 and []
f(undefined, [0]); //prints [0]
f(0, [0]); //only prints [0]!!!

Proposal
Reduce the likelihood of such bugs, by adding a flag --noImplicitBooleanConversion that will make the following expressions illegal:

if(a) {}
if(!a) {}

when a has the type 'number | undefined' or 'string | undefined' (and possibly more involving 'null' or combinations of 'number' and 'string')

I also suggest that in this case, the coercion can be forced with:

if!(a) {}
if!(!a) {}

which are then legal.

Coercion to boolean of variables where the type is just 'number' or 'string' would always remain legal.

Further discussion

The above only addresses one very common pattern, and doesn't address the expression !a outside of the if context. Finding a suitable "override" syntax might be challenging (the equivalent of if! for the above case).
It also doesn't address expressions like 'a && f(a)', 'a || 5' or '(a ? a : 5)', which might also produce unexpected results when a is of type 'number | undefined'. These could be explored.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Jul 13, 2016
@buola
Copy link
Author

buola commented Jul 13, 2016

I realized that the override syntax might not be necessary, since even if '!a' was made illegal when 'a' is of type 'number|undefined', '!a!' would be legal, and a suitable override. 'if(a!)' would also be legal, and generate identical code to 'if(a)'.
The only case where it might produce an unexpected result is in expressions like 'a! && 5', which has type 'number', while 'a && 5' has type 'number | undefined'

@RyanCavanaugh RyanCavanaugh added Out of Scope This idea sits outside of the TypeScript language design constraints and removed In Discussion Not yet reached consensus labels Aug 22, 2016
@RyanCavanaugh
Copy link
Member

This is too idiomatic to ban everywhere, even under a flag (flags are not free and need to justify their existence). The TSLint rule mentioned above is the right place to disallow idiomatic JS expressions.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants