Currently operators like "+" are defined such that they match their semantics in JS. The below are all allowed by the compiler and produce the shown values, even with --strictNullChecks on.
2 + 'a' => "2a"null + 'a' => "nulla" (!)2 - null => 2I propose letting users opt in (maybe via some --strictOperators) to strict operator behavior. Concretely I think this means:
+, and += to just number and string, e.g. for the former only declarejs
function +(a: number, b: number): number;
function +(a: string, b: string): string;
- and -= to just number(any should continue to work as normal, of course.)
Relevant spec section:
https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#419-binary-operators
See also "Expression operators" in the strictNullTypes change: https://github.com/Microsoft/TypeScript/pull/7140
and in particular this rationale: https://github.com/Microsoft/TypeScript/pull/7140#issuecomment-186432250
This would fall under of "stricter" TypeScript, https://github.com/Microsoft/TypeScript/issues/274 .
_number + string_ is actually quite common in JavaScript land and will probably not happen as it moves the convenience - type safety slider too much towards safety.
_null + string_ should be disabled as a part of strictNullChecks.
A number of wat things are disabled in TypeScript e.g. [] + [] (valid JavaScript, produces "") is an error in TypeScript. Similarly "hello" + 1 is allowed (like I mentioned) but "hello" - 1 is an error :rose:
@basarat I really struggle when the argument "because that's how Javascript does it" is applied. Particularly in cases like this where I think the cognitive load on the developer is increased by decisions to stick to the Javascript way. Not because it's unclear how + behaves, rather that is creates cognitive dissonance with the rest of the type system:
let s: string;
let n: number;
s = n; // ERROR: number is not assignable to string
n = s; // ERROR: string is not assignable to number
let res = s + n; // OK: really?
I understand that + is defined by the spec to work on combinations of number and string and so has well-defined behaviour, but given the example above I think it's more confusing than useful for it to have been defined in this way (the Javascript way). Particularly when explicit conversion is so simple and more readable.
@myitcv how is different from https://github.com/Microsoft/TypeScript/issues/7746?
@mhegazy because as I understand it, there is no coercion when it comes to +; it's simply specified to operate on various combinations of types.
@aleksey-bykov do you agree that this suggestion encompasses the one in #7746?
i agree, thank you for considering
Approved behavior change: under --strictNullChecks it should be an error to use a possibly-null/possibly-undefined operand in a +, -, /, *, |, &, ^, or ** expression. One exception is that string + nullable is still OK since that's very common for producing debugging strings.
Thanks for looking at this! That behavior change would be most welcome!
Do you have any thoughts on the other bits of the request (in particular string + number)?
Also, I guess
`${string}${nullable}`
is still legal for debugging purposes even if string + nullable were made illegal.
We don't want the string template syntax to be different from the basic concat rules in terms of type system behavior; one is just sugar for the other and it'd be weird to have different rules.
I think this is a duplicate of #12795 which was fixed in #13483
The null part, yes. I am still a little disappointed that type checking is basically disabled if the expression involves a string, e.g. this is legal and there's no opting out:
let x = {a: 3};
let y = x + 'a';
For tslint users, we have https://palantir.github.io/tslint/rules/restrict-plus-operands/
Edit: this won't help for template strings, at least not yet: https://github.com/palantir/tslint/issues/3670
seems already fixed
Most helpful comment
_number + string_ is actually quite common in JavaScript land and will probably not happen as it moves the
convenience - type safetyslider too much towards safety._null + string_ should be disabled as a part of
strictNullChecks.Note:
A number of
watthings are disabled in TypeScript e.g.[] + [](valid JavaScript, produces "") is an error in TypeScript. Similarly"hello" + 1is allowed (like I mentioned) but"hello" - 1is an error :rose: