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: stricter operators #7989

Open
evmar opened this Issue Apr 10, 2016 · 14 comments

Comments

Projects
None yet
9 participants
@evmar
Contributor

evmar commented Apr 10, 2016

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 => 2

I propose letting users opt in (maybe via some --strictOperators) to strict operator behavior. Concretely I think this means:

  • restrict +, and += to just number and string, e.g. for the former only declare

    function +(a: number, b: number): number;
    function +(a: string, b: string): string;
  • restrict - 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: #7140
and in particular this rationale: #7140 (comment)

This would fall under of "stricter" TypeScript, #274 .

@basarat

This comment has been minimized.

Contributor

basarat commented Apr 10, 2016

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.

Note:

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 🌹

@aleksey-bykov

This comment has been minimized.

aleksey-bykov commented Apr 10, 2016

related #7746

@myitcv

This comment has been minimized.

myitcv commented Apr 10, 2016

@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.

@mhegazy

This comment has been minimized.

Contributor

mhegazy commented Apr 11, 2016

@myitcv how is different from #7746?

@myitcv

This comment has been minimized.

myitcv commented Apr 11, 2016

@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.

@mhegazy

This comment has been minimized.

Contributor

mhegazy commented Apr 11, 2016

@aleksey-bykov do you agree that this suggestion encompasses the one in #7746?

@aleksey-bykov

This comment has been minimized.

aleksey-bykov commented Jun 7, 2016

i agree, thank you for considering

@RyanCavanaugh

This comment has been minimized.

Member

RyanCavanaugh commented Jun 9, 2016

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.

@mhegazy mhegazy added this to the Community milestone Jun 9, 2016

@evmar

This comment has been minimized.

Contributor

evmar commented Jun 9, 2016

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.

@RyanCavanaugh

This comment has been minimized.

Member

RyanCavanaugh commented Jun 9, 2016

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.

@TimvdLippe

This comment has been minimized.

TimvdLippe commented Feb 13, 2017

I think this is a duplicate of #12795 which was fixed in #13483

@evmar

This comment has been minimized.

Contributor

evmar commented Feb 14, 2017

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';
@OliverJAsh

This comment has been minimized.

OliverJAsh commented Sep 25, 2017

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: palantir/tslint#3670

@Kingwl

This comment has been minimized.

Contributor

Kingwl commented Apr 11, 2018

seems already fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment