4 ms·
> One can explicitly specify the type arguments of a generic function invocation or generic class instantiation in TypeScript. // TypeScript add<number>(4,
by syspec 4y ago
> One can explicitly specify the type arguments of a generic function invocation or generic class instantiation in TypeScript.
// TypeScript
add<number>(4, 5)
new Point<bigint>(4n, 5n)
> The above syntax is already valid JavaScript that users may rely on, so we cannot use this syntax as-is. We expect some form of new syntax that could be used to resolve this ambiguity. No specific solution is proposed at this point of time, but one example option is to use a syntactic prefix such as :
// Types Annotations - example syntax solution
add::<number>(4, 5)
new Point::<bigint>(4n, 5n)
> These type arguments (::<type>) would be ignored by the JavaScript runtime. It would be reasonable for this non-ambiguous syntax to be adopted in TypeScript as well.
----
Hmm I didn't know this, so I tried it myself in Chrome's console... sure enough it works...
new DOMPoint<Number>(4,5)
Given that the above works in the browser, what exactly is it doing? I've never seen angle brackets used that way in vanilla JS code
- Matheus28 4y ago((new DOMPoint) < Number) > (4,5) Comma operator makes (4,5) = 5
- methyl 4y agoIt just evaluates to false, as this is just two comparison operations. It's easier to comprehend if add a parentheses around first operation as such: (new DOMPoint < Number) > (4, 5) (new DOMPoint < Number) evaluates to true and it becomes (true) > (4, 5). Because (foo, bar, baz) syntax always evaluates the last item, we can finally simplify it into (true > 5), which surely enough in Javascript evaluates to false.
- evan_ 4y agoIt's just less than/greater than: https://astexplorer.net/#/gist/b0dff7bdaf1d8f9024fe18fda70a9a11/084c148af609421337fbfb94977f8352448600a7 https://astexplorer.net/#/gist/b0dff7bdaf1d8f9024fe18fda70a9...
- colejohnson66 4y agoIMHO, the "turbofish" syntax (popularized by Rust) is ugly and should not be used. The reasoning of syntax ambiguity is also a lame one because C# manages just fine without it. But to then say that: > The above syntax is already valid JavaScript that users may rely on, so we cannot use this syntax as-is. What users would be using said syntax? Why would one compare a function to a type? If we're making a backwards incompatible change, just say that `func < type` is a syntax error unless immediately followed by the rest of a call. IMO, in any spec committee, if a naysayer says that "someone may be using that syntax", they should be required to prove it. Prove that someone is comparing a function to be less than a type, and why they'd do such a thing. Honestly, I don't see how this can be done in a backwards compatible way short of type annotations in comments. Just rip the bandaid off and have WHATWG say that TypeScript is a valid runtime and allow `<script src="..." type="typescript">`. Deno manages to have a TypeScript runtime just fine.
- codethief 4y ago> What users would be using said syntax? Why would one compare a function to a type? Possibly the people behind JSFuck and derivatives. :)
- crooked-v 4y ago> Why would one compare a function to a type? Aggressively minified and optimized JS code results in all sorts of weird things.
- colejohnson66 4y agoSure, but if a minifier/optimizer wants a “truthy” value, they can just use “1”. It’d be a pretty bad minifier if it turned something needing a truthy value into anything more than that. Unless one can find some minifier producing said example, it’s a bad argument.
- jffry 4y agoIt's essentially unknowable if anybody has produced code out there that is like this, but the point still stands that it is valid code. If you want to uphold a commitment to backwards compatibility, you simply cannot extend your language in a way that might possibly change the behavior of valid-but-nonsensical code in the wild.
- runarberg 4y agonumber is a type but also a valid identifier, so you can do things like: const number = 5; function fn(number: number): number That means that we can’t always know whether we mean the type or the constant when we type: a<number>(b)
- dnsco 4y agoThe turbofish resolves a bunch of syntax ambiguities[1]. Apparently C++ parsing is undecidable, so building an AST requires arbitrary template instantiation (and C++ templates are turing complete). The turbofish is a compromise that allows the parser to stay simple. I know there were efforts to remove it, but it appears to be here to stay. https://github.com/rust-lang/rust/blob/master/src/test/ui/parser/bastion-of-the-turbofish.rs https://github.com/rust-lang/rust/blob/master/src/test/ui/pa...
- epidemian 4y ago> Given that the above works in the browser, what exactly is it doing? Oh, buckle up! new DOMPoint<Number>(4,5) Let's first clean things up a bit: DOMPoint an Number are just identifiers. So, let's replace those with a and b: new a<b>(4,5) Let's also add some spacing around these tokens to distinguish them better: new a < b > (4, 5) Yep, those < and > are comparison operators. And let's also add some parentheses to make clear the order of operations in these comparisons. The above expression is equivalent to: (new a < b) > (4, 5) Now, let's remember that a is DOMPoint, so `new a` is just instantiating a new DOMPoint object. Yep, the parentheses at the end of the `new Something` calls are optional if no parameters are passed. > new DOMPoint DOMPoint { x: 0, y: 0, z: 0, w: 1 } (That's the result of trying that out on a JS console. The initial > on the first line is the REPL prompt, not part of the JS syntax. And the second line is what the REPL prints.) So the < operator is comparing a DOMPoint object to b, which is Number, which is just a constructor function. IIRC, what JS does is these kind of situations is to convert both operands to strings and then compare those. > (new DOMPoint).toString() "[object DOMPoint]" > Number.toString() "function Number() { [native code] }" So the first < comparison is going to compare these two strings, and since '[' is less than 'f' (of course... ASCII), the < result will be `true`. The whole expression can then be reduced to: true > (4, 5) The right-hand side of this > operation, `(4, 5)`, is curious. The parentheses are just normal parentheses for grouping expressions, but what's inside of them are two expression joined together by the comma operator[1]! Basically, both expressions, 4 and 5, are evaluated, one after the other, and the result of the whole is the result of the last one: > 4, 5 5 So, we're almost there! The whole thing can now be reduced to: true > 5 Since one of the operands is a number, JS tries to convert the other one to a number too. `true` converted to a number yields 1, which is not bigger than 5 — finally, something that makes sense! So now we know why the whole thing that looks like TypeScript but isn't, is valid JavaScript and evaluates to false :) > new DOMPoint<Number>(4,5) false 1: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- JadeNB 4y agotrue > 5 > Since one of the operands is a number, JS tries to convert the other one to a number too. `false` converted to a number yields 0, which is not bigger than 5 — finally, something that makes sense! You meant that `true`, not `false` which doesn't appear in this partially evaluated version, is numified, right?
- IshKebab 4y agoI don't see why they can't just have `"use types";` or whatever like they did for strict mode.