Typescript: (0,eval) produces TS2695

Created on 16 Dec 2016  Â·  9Comments  Â·  Source: microsoft/TypeScript

TypeScript Version: 2.1.4

(0,eval)('var x = 10');

Expected behavior:
Compile fine.

Actual behavior:
error TS2695: Left side of comma operator is unused and has no side effects.

See also at TS Playground.

(0,eval) is a well-used convenience syntax for invoking eval with a global scope (as opposed to the scope of the caller).

One possible workaround is: (eval||null). But that's longer and most of all — hard to Google the reasoning behind. Whereas (0,eval) is easy to find a detailed explanation for.

Please make it not error.

Fixed Suggestion help wanted

Most helpful comment

(0,eval) is a hack, you can just use your own global eval like:

const myEval = eval;
myEval(`var x = 10`);

I'm personally fine with TS erroring out on this. It is a _really_ edgy case.

All 9 comments

(0,eval) is a hack, you can just use your own global eval like:

const myEval = eval;
myEval(`var x = 10`);

I'm personally fine with TS erroring out on this. It is a _really_ edgy case.

Calling something hack or edge case isn't relevant. Infinity is real proper edge case, yet it produces no error: 1+Infinity. (function(){ })() is a definite absolute hack, yet no errors pop up.

What's relevant is the usage of a given pattern. (0,eval) is widely used, even in pretty much cutting edge libraries:

https://github.com/systemjs/systemjs/blob/5ed69b6344e8fc1cd43bf758350b2236f57e1499/lib/global-eval.js#L96

Widely-used well-known googlable "hacks" should not trigger errors. I think this check was added recently — I don't think it generated this noise in 2.0.6. It's a regression and may cause undue friction for migrating code from JS.

@mihailik SystemJS is a _module loader_, it's meant to evaluate code so it's the one place where you might find this hack outside of transpiled code.

I agree there is a bar here of what we want to honor or not. (function() {})() for scoping is hardly a hack in "idiomatic JS". Relying on whether or not eval is referenced directly or indirectly for defining global variables seems like a much much bigger stretch.

Allowing strictly eval as a special case right operand here seems fine.

Totally agree with eval being the only special exception here.

Certain type of code relies on eval: binding frameworks, dynamic code transforms, loaders and so on. Indirect (0,eval) is an important feature in such cases.

Couple more examples:

https://github.com/knockout/knockout/blob/241c26ca82e6e4b3eaee39e3dc0a92f85bc1df0c/build/fragments/extern-pre.js#L4

https://github.com/facebook/react/blob/c78464f8ea9a5b00ec80252d20a71a1482210e57/scripts/bench/measure.py#L24

For reference, background to current behaviour can be found in #10814 which was prompted by the scenario in #10802.

@yortus thanks for the providing the context. It seems a bit hand-holdy given that it's not a type level rule and that people can generally be expected to know the syntax for control flow constructs. The comma operator is definitely an easy thing to get wrong and probably something I would otherwise want to ban with a linter but not necessarily at the language level.

Using void operator disables the check, so you can use (void 0,eval)('var x = 10');

Accepting PRs to allow strictly the identifier eval as the right-side comma operand without error

Was this page helpful?
0 / 5 - 0 ratings