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

if-else and switch as expressions #10841

Closed
shelby3 opened this issue Sep 10, 2016 · 28 comments
Closed

if-else and switch as expressions #10841

shelby3 opened this issue Sep 10, 2016 · 28 comments
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript

Comments

@shelby3
Copy link

shelby3 commented Sep 10, 2016

There are scenarios that require we produce a result from an if-else or switch which is not returned:

function f(z) {}
const x = 1, y = 2, z   // Error z must be initialized
if (x) z = y            // Error can't reassign const z
else z = true
f(z)

Even if we abandon const z for let z, the code above is noisy (not DNRY, SPOT, and encapsulated) and if we modify the spelling of the identifier z, then we have to remember to change it every where it is assigned in the if-else (or switch) statement.

Some languages (e.g. Scala) allow if-else and switch to optionally be used as expressions:

function f(z) {}
const x = 1, y = 2,
      z = if (x) y else true
f(z)

Obviously we could use ternary operator expression instead:

function f(z) {}
const x = 1, y = 2,
      z = x ? y : true
f(z)

But that won't help us for switch, nor is the ternary able to employ blocks containing (multiple) statements where only the value of the last statement or expression is the result value:

function f(z) {}
const x = 1, y = 2,
      z = if (x) { for(var i = 0; ++i < y;); i } else true
f(z)

Additionally an expression can be placed inline as a function parameter argument:

function f(z) {}
const x = 1, y = 2
f(if (x) { for(var i = 0; ++i < y;); i } else true)

The transpiling to JavaScript is straightforward:

function f(z) {}
var x = 1, y = 2
f((function() { if (x) { for(var i = 0; ++i < y;); return i } else return true })())

I presume it is not necessary for me to write multiple line switch examples for the reader to visualize the utility of this suggested feature.

The only potential blocking issue I am contemplating is whether the parser grammar has any conflict with accepting if-else and switch as expressions.

As example of a language which supports if-else and match (switch variant) as expressions is Scala.

@kitsonk
Copy link
Contributor

kitsonk commented Sep 10, 2016

You seem to be wanting to change ECMAScript, and TypeScript is the not the right way. I assume you have reviewed the design goals of TypeScript. In particular goal, in particular:

  1. Avoid adding expression-level syntax.

Also there is the non-goal:

  1. Exactly mimic the design of existing languages. Instead, use the behavior of JavaScript and the intentions of program authors as a guide for what makes the most sense in the language.

If there is an improvement to the initializer syntax for const then it likely should be addressed with ECMAScript via ES Discuss. The TypeScript core team have made it very clear on a number of occasions there has to be a hugely compelling reason to diverge from the underlying ECMAScript syntax, especially if it is not directly related to the erasable type system.

@shelby3
Copy link
Author

shelby3 commented Sep 10, 2016

@kitsonk wrote:

You seem to be wanting to change ECMAScript, and TypeScript is the not the right way.

ECMAScript is a very slow moving standard, and I don't even have a clue of how to build up enough support to get a feature change pushed through there. When there are huge design wins that are naturally superb without any notable negative implications, then transpilers are one way of getting the functionality sooner and influencing the direction of ECMAScript by validating the popularity, utility, and soundness of improvements.

There are at least two reasons I believe TypeScript may be not only the right way but also the _only way_ in this particular case:

  1. There are certain essential features of TypeScript that are not available in any other transpiler. If you need these features and also need this suggested improvement, then you are forced to request it in TypeScript. Also everything I am writing on TypeScript, is also intended to try to influence Google's upcoming SoundScript derivative and any other potential derivative. I realize this is a crucial window of opportunity to influence SoundScript. Google has stated they hope to get their constructs submitted to ECMAScript in the future.
  2. In this particular case, TypeScript's unique (amongst transpilers) first-class union typing and robust inference is absolutely essential to implementing this feature without needing ugly type annotations which would otherwise make the feature basically not that beneficial.

One transpiler which supports this feature is Nim, but it has so much heavy-weight baggage that I can't consider it. CoffeeScript also supports this feature, but is too limited to meet my needs. I do appreciate TypeScript's light-weight design goals and avoiding "everything and the kitchen sink" approach to adding features. That is why I am only suggesting what I think are features which are very frequently required and are also light-weight and/or very specific to TypeScript's main goal of typing (and tracking) ECMAScript. Brenden Eich referenced CoffeeScript w.r.t. to influencing his thinking about the future of JavaScript.

I assume you have reviewed the design goals of TypeScript.

Yes I had read it.

In particular goal, in particular:

  1. Avoid adding expression-level syntax.

I am not adding any keywords nor changing the syntax any keywords. I am proposing to interpret two existing keywords as both statements and expressions, which albeit does add syntax for expressions that was only formerly available as statements, it doesn't add syntax which didn't already exist and isn't already familiar to all JavaScript users. And the emitted JavaScript isn't mangled and is very clear.

TypeScript has added expression level syntax sugar such as index properties (granted that is constrained to the expressions for property name slots). And that is entirely new syntax that is very unfamiliar to JavaScript programmers.

A general first-class expression level syntax added by TypeScript is I believe function type parameters. Yes it is entirely erased, but nevertheless it is very unfamiliar (to JavaScript programmers) new expression-level syntax.

Also there is the non-goal:

  1. Exactly mimic the design of existing languages. Instead, use the behavior of JavaScript and the intentions of program authors as a guide for what makes the most sense in the language.

I am not proposing to _exactly_ mimic the design of existing languages. The ability to treat if-else and switch as expressions is a generally necessary construct of programming language design, not something specific to some programming languages. The reason some programming languages don't have the feature, is because they were not designed with the necessary forethought.

And the intentions of program authors is very much inline with this feature suggestion, because there is no other way to accomplish it, which respects the general software engineering principles DNRY, SPOT (Single-Point-Of-Truth), and encapsulation. Thus it makes the most sense and entirely agrees with 1).

If there is an improvement to the initializer syntax for const then it likely should be addressed with ECMAScript via ES Discuss.

This initialization for a const is not the only reason for proposing this suggested feature. Have you studied closely the OP and the point about DNRY, SPOT, and encapsulation. Do I need to write a very long switch statement to illustrate to you how many times the z = assignment is repeated without this suggested feature?

This is already a feature of JavaScript via the anonymous function construct which this suggested sugar would transpile to. So it isn't like we are doing something that JavaScript programmers can't and don't already do. I am proposing sugar to make it less fugly to write.

The TypeScript core team have made it very clear on a number of occasions there has to be a hugely compelling reason to diverge from the underlying ECMAScript syntax, especially if it is not directly related to the erasable type system.

The typing of the suggested sugar is entirely erased in the emitted JavaScript and the emitted code very closely resembles the sugared code minus the fugly anonymous function wrapper. No metadata is emitted.

Also apparently informing TypeScript that these are expressions in this context, would enable TypeScript's inference engine to infer the union type, which it can't do currently when they are considered only as statements with return inside the anonymous function. You can verify this by substituting the ternary for if-else as in my example feeding the transpiled JavaScript to TypeScript.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Out of Scope This idea sits outside of the TypeScript language design constraints labels Sep 10, 2016
@RyanCavanaugh
Copy link
Member

The fact that the ECMA committee doesn't move with the speed/openness many would prefer doesn't change who's responsible for adding new expression-level syntax to JS (re-using existing keywords doesn't mean it's not new syntax).

@shelby3
Copy link
Author

shelby3 commented Sep 10, 2016

P.S. Thanks for marking it as a Suggestion. Out-of-Scope is okay for at least it meets my minimum goals of documenting it as a valid suggestion for potential derivatives of TypeScript, ECMAScript committees, etc.

@RyanCavanaugh wrote:

The fact that the ECMA committee doesn't move with the speed/openness many would prefer doesn't change who's responsible for adding new expression-level syntax to JS (re-using existing keywords doesn't mean it's not new syntax).

Did TypeScript wait for EMCAScript to add type parameters to first-class function expression syntax before adding them to TypeScript? Granted type parameters are germane to typing which is TypeScript's main goal apparently. But it is entirely new syntax that isn't even remotely similar to anything in EMCAScript.

_Another problem is that TypeScript can't currently type the transpiled JavaScript with the anonymous function._ So there really isn't any way to do what we normally can do in JavaScript in TypeScript!

function f(z) {}
var x = 1, y = 2
f((function() { if (x) { for(var i = 0; ++i < y;); return i } else return true })()) // Error "No best common type exists among return expressions."

TypeScript can't infer the type number | boolean above.

So I am forced to annotate the type which makes it more verbosely fugly:

function f(z) {}
var x = 1, y = 2
f((function():number | boolean { if (x) { for(var i = 0; ++i < y;); return i } else return true })())

Should I file a bug or is that intended behavior? And would treating if-else as an expression cause the inference engine to resolve the type (as it does for the ternary expression)?

Obviously the goals are guidelines only and the design goals document says sometimes the goals will be conflicting.

Given the great amount of effort that has been poured into TypeScript to support type narrowing (discrimination) guards on if-else and switch, a feature which is important for the non-fugly use of this core TypeScript capability seems to me to be in scope and arguably worth discussing as a worthwhile change.

@shelby3
Copy link
Author

shelby3 commented Sep 10, 2016

@shelby3 wrote:

Also everything I am writing on TypeScript, is also intended to try to influence Google's upcoming SoundScript derivative and any other potential derivative. I realize this is a crucial window of opportunity to influence SoundScript. Google has stated they hope to get their constructs submitted to ECMAScript in the future.

Also I forgot to mention by "other potential derivative", that there is a small possibility that I may in near-future (if my plans proceed as hoped) hire someone to add the features I want to the toolchain and maintain the fork for me. And influence what I want by making a variant popular. Obviously that is pie-in-the-sky at the moment, but isn't as if I haven't produced million users software before. Obviously it is best to work within the larger community for the moment, so best to record these ideas here and observe reception.

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@kitsonk wrote:

If there is an improvement to the initializer syntax for const then it likely should be addressed with ECMAScript via ES Discuss.

Posted to ES Discuss and also the discussion group for SoundScript, for continuing discussion here or there, applicable to acceptance in any relevant scope of responsibility or willingness to adopt.


Also the proposed Units of Measure (#364) is yet another example where there is considerable popular support for a very unfamiliar (to EMCAScript) expression-level syntax; and which appears to me to be a special case syntax pollution that could instead be more generally accommodated with nominal types. Hypocrisy of stated goals of TypeScript or is it because anything germane to improving typing receives a pass? (I hope the bias isn't the affiliation to Microsoft projects such as F#)

@rtm
Copy link

rtm commented Sep 11, 2016

Accusations of hypocrisy and bias are hardly constructive.

TS has a very clear mission which your proposal does not align with. Period.

Your basic idea has already been proposed for ES in the form of the do { } construct, which has been discussed in detail.

@spion
Copy link

spion commented Sep 11, 2016

The difference with "Units of measure" is that you can erase all the expression-level type hints and get valid JavaScript. Thats not the case with the above modifications to if/switch.

FWIW there is a pattern matching proposal (which has been sitting for a while w/o anyone to properly champion it) here: http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching and I believe it modifies switch to be usable in expressions in certain cases.

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@rtm wrote:

Accusations of hypocrisy and bias are hardly constructive.

Question marks and hope are not accusations. Reading comprehension matters.

TS has a very clear mission which your proposal does not align with. Period.

Is that your opinion or is there some basis other than what has already been stated here?

What is that clear mission succinctly?

Your basic idea has already been proposed for ES in the form of the do { } construct, which has been discussed in detail.

Link please?


@spoin wrote:

The difference with "Units of measure" is that you can erase all the expression-level type hints and get valid JavaScript. Thats not the case with the above modifications to if/switch.

I presume you mean you can erase (elide) it without any transpilation of remaining code without the type hints. Because afaik erasure (as opposed to reification) in programming language design context usually means to not put any metadata about types in the runtime, and doesn't concern itself with compilation of source code to the target runtime.

Yet there are artifacts of TypeScript which can't simply be elided and produce valid JavaScript, e.g. index properties.

What is the consistency of the goals succinctly? My interpretation is that the goals are to minimize the transpiling (on a cost vs. benefit analysis) and to prioritize erasable typing over other feature enhancements. Is that approximately correct?

Again I reiterate that I am in full support of a light-weight transpiling layer. I reject JavaScript compilers for such as Scala and Nim, because I can't even readily comprehend the JavaScript they emit and interoperability with JavaScript is an important facet to maintain at this juncture. I am enthused about Google's SoundScript idea of possibily integrating the TypeScript syntax into the VM, to make my toolset cycle even more efficient (in addition to potential performance gains). Just a few moments ago, I wrote a defense of TypeScript against some claims made by N4JS.

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@spoin wrote:

FWIW there is a pattern matching proposal (which has been sitting for a while w/o anyone to properly champion it) here: http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching and I believe it modifies switch to be usable in expressions in certain cases.

Thanks. That is very much in the constructive spirit of aiming for solutions. I also found some examples employing the alternative match keyword. (I think I had seen that proposal before and had forgotten)

Since that is already a proposal for ECMAScript, then doesn't that give us some basis to consider adding it to TypeScript on a very careful cost vs. benefit analysis? (including the cost of prematurely adopting a proposal that might not gain sufficient support to become a standard someday, and noting my points upthread about how minimal the transpile footprint is for this, only wrapping in an anonymous function).

Note however, the problem is that proposal also carries with it a lot of new syntax for matching patterns, but perhaps we could choose not to implement that facet of the proposal, which would maintain the very minimal transpile overhead (as stated above) and would still be compatible with the proposal.

I would still argue for the need for the expression if-else because it would be verbose to use a switch expression when an if-else expression would suffice (although some of the if-else cases can be handled by the ternary operator expression).

@MatAtBread
Copy link

There is an ECMA script proposal (apologies for not having a link to hand) for using the 'do' keyword to introduce a statement lexical environment from within an expression, which achieves what you want, while being general enough to support many other statements in addition to if and switch.

For example:

X = do { if (test) 10 ; else 20 ; };

@rtm
Copy link

rtm commented Sep 11, 2016

You might as well try beating your head against a brick wall as to continue
to push this proposal in this forum.
No one cares whether there is a "need" (there probably is), nor whether
your solution is the best one (it probably isn't).
The point is that TypeScript is not about new language extensions, as is
clearly stated in its mission, and as already pointed out to you earlier in
the thread.
Merely being a "proposal" is far away from being incorporated in the
language or reaching the advanced stages of deliberation for almost certain
inclusion in the next version of the language.

With regard to the do proposal, it was the fourth result from a google
search for "esdiscuss do":
https://esdiscuss.org/topic/generalize-do-expressions-to-statements-in-general

Bob

On Sun, Sep 11, 2016 at 4:35 PM, shelby3 notifications@github.com wrote:

@spoin https://github.com/spoin wrote:

FWIW there is a pattern matching proposal (which has been sitting for a
while w/o anyone to properly champion it) here:
http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching and I
believe it modifies switch to be usable in expressions in certain cases.

Thanks. I also found some examples
http://dmitrysoshnikov.com/notes/pattern-matching/#multi-case-match
employing the alternative match keyword.

Since that is already a proposal for ECMAScript, then doesn't that give us
some basis to consider adding it to TypeScript on a very careful cost vs.
benefit analysis? (including the cost of prematurely adopting a proposal
that might not gain sufficient support to become a standard someday, and
noting my points upthread about how minimal the transpile footprint is for
this, only wrapping in an anonymous function).

I would still argue for the need for the expression if-else because it
would be verbose to use a switch expression when an if-else expression
would suffice (although some of the if-else cases can be handled by the
ternary operator expression).


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#10841 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABfR8-19gfeI3ZFj1HDdMkiVI3FrXDBks5qo-BxgaJpZM4J5yCu
.

@kitsonk
Copy link
Contributor

kitsonk commented Sep 11, 2016

@MatAtBread it is a Stage 0 proposal documented here: http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions

It is listed as still active on the Stage 0 proposals page though clearly it isn't being actively championed at the moment, as the last edit was 2011.

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@MatAtBread thanks for the summary. I am doubting if there is any advantage to introducing superfluous syntax instead of accepting my proposal, because then if(true) {} could be used every where do {} would have been and mine is more concise for the if-else usage, given that concision is one of the main points since we can already achieve it by wrapping in an anonymous function, although apparently TypeScript currently doesn't subsume to the union type when it is not an expression. And expression switch is already covered by that other ES proposal mentioned upthread.

Edit: a do {} without a trailing while() is not only a shocking change in semantics, it has no point of being used as statement. I prefer the unification of if-else as both an expression and a statement. Unification reduces proliferation.

On Monday, September 12, 2016 at 1:18:19 AM UTC+8, Shelby Moore wrote:

On Wednesday, October 14, 2015 at 7:46:42 PM UTC+8, Andreas Rossberg wrote:

Is there any particular benefit to removing void, other than making
a (_very large) language slightly smaller?
...
PS: Once we have[add] do-expressions, do{} will be _the shortest way
to
produce undefined. :)

Oh the irony :)

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@rtm wrote:

You might as well try beating your head against a brick wall as to continue to push this proposal in this forum.

Lol, I like the fortitude. Notwithstanding that I haven't entirely abandoned the remote possibility of convincing sufficient people that this feature should be added to TypeScript, but I am not pushing hard or expecting, perhaps you missed my other statemenets upthread quoted as follows:

P.S. Thanks for marking it as a Suggestion. Out-of-Scope is okay for at least it meets my minimum goals of documenting it as a valid suggestion for potential derivatives of TypeScript, ECMAScript committees, etc.

Also everything I am writing on TypeScript, is also intended to try to influence Google's upcoming SoundScript derivative and any other potential derivative. I realize this is a crucial window of opportunity to influence SoundScript. Google has stated they hope to get their constructs submitted to ECMAScript in the future.

Also I forgot to mention by "other potential derivative", that there is a small possibility that I may in near-future (if my plans proceed as hoped) hire someone to add the features I want to the toolchain and maintain the fork for me. And influence what I want by making a variant popular. Obviously that is pie-in-the-sky at the moment

@rtm wrote:

No one cares whether there is a "need" (there probably is), nor whether your solution is the best one (it probably isn't).

Maybe some care about clarifying the interpretation of the scope of TypeScript's goals. I for one am still finding ambiguity in every attempt to do so, juxtaposed against the contradictions in features that have been added.

I do believe there may be a clearer interpretation and that is one of my goals by continuing the discussion.

@rtm wrote:

The point is that TypeScript is not about new language extensions, as is clearly stated in its mission, and as already pointed out to you earlier in the thread.

Tracking language extensions is obviously one of the goals of TypeScript. Also TypeScript has added expression-level syntax that isn't merely elided from the emitted output. The demarcation that you are claiming is clear, is actually fuzzy and apparently somewhat subjective.

Even if you claim that anything to do with typing (even expression-level) is out-of-scope of ES language extension and thus the exclusive domain of TypeScript, then I can still argue that adding typing was discussed on ES-DISCUSS this month.

Even statement versus expression is also involved with typing, since statements have essentially the never type and expressions can be populated with instantiable types.

Merely being a "proposal" is far away from being incorporated in the language or reaching the advanced stages of deliberation for almost certain inclusion in the next version of the language.

Agreed, but that didn't stop TypeScript from adding features that might not be in ECMAScript until many years from now if ever.

With regard to the do proposal, it was the fourth result from a google
search for "esdiscuss do":
https://esdiscuss.org/topic/generalize-do-expressions-to-statements-in-general

I wasn't clear if you weren't referring to a proposal made in some discussion in the TypeScript community, i.e. that someone else like me had attempted to propose something for ES in the TypeScript community. Thus I wouldn't have thought to search ES-DISCUSS. Also please know that I haven't not been aware of how EMCAScript is developed. I had no clue at all that ES-DISCUSS even exists before @kitsonk mentioned it. I am not even clear as to where the official discussion takes place, how to add proposals, etc.. Hadn't applied the time yet and not sure if that is a good use of my focus.

Generally and lately I tend to lean towards being oblivious of standards committees because my experience with standards committees has been they are a waste of my time. I am for example listed as a contributor to CSS2.1, but my attempts to help on CSS3 and WebSockets were a total waste of my effort (they conflated the framing and data layer because they were worried about making the implementation simplistic, same to very poor design decision for the Opus container).

@kitsonk
Copy link
Contributor

kitsonk commented Sep 11, 2016

I had no clue at all that ES-DISCUSS even exists before @kitsonk mentioned it. I am not even clear as to where the official discussion takes place, how to add proposals, etc..

Technical Committee 39 is the governing body for ECMAScript (ECMA262). The current official specification is here. Their GitHub repo is here. There is a proposals repo and a process document of how proposals are progressed. TC39 meet bimonthly in person to continue to move forward with the standard. They have published contribution guidelines. For a standards organisation, they are one of the most open and transparent ones, in my opinion.

My opinion is that around the time of the ratification of ES2015, the processes bedded down for proposals (because ES2015 was a bit of a ruby scrum) and the process has added a great deal of transparency to the process. The problem was that ES2016 was fairly light (especially compared to the behemoth that was ES2015) though it is looking like ES2017 is picking up a bit with 5 proposals at Stage 4, ready for ratification.

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@shelby3 wrote:

I presume you mean you can erase (elide) it without any transpilation of remaining code without the type hints. Because afaik erasure (as opposed to reification) in programming language design context usually _means to not put any metadata about types in the runtime_, and doesn't concern itself with compilation of source code to the target runtime.

Yet there are artifacts of TypeScript which can't simply be elided and produce valid JavaScript, e.g. index properties.

What is the consistency of the goals succinctly? My interpretation is that the goals are to minimize the transpiling (on a cost vs. benefit analysis) and to prioritize erasable typing over other feature enhancements. Is that approximately correct?

Major design decision quagmire which makes that the inviolability of that goal seem unwise?

Or are we so purist on the goals that we instead prefer unsoundness and manual tsuris instead?

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@kitsonk I think the stance I will take is if this feature becomes important enough to me to allocate resources to paying someone to champion it, then I will direct them to this thread. I won't champion it myself because I don't have the time to do that activity.

I filed this issue not as top priority concern, but just to get it out of the way as something I wanted to register as an issue. And I am actually happy it is on my Github activity archive and not spread around a dozens of mailing list discussion groups I have participated in over the decades.

It doesn't mean everything I write about has to be immediately actionable.

Our discussion also caused me to think more about the goals of TypeScript.

Even I am not expecting any immediate action (nor even expecting an enthusiastic reception for) the typeclasses proposal I am developing as an issue. The point is to document what I think and enjoin any discussion. This can help my planning process as to where TypeScript fits into my current strategy.

Given I only started learning TypeScript 48 hours or so ago, I am trying to lay down as quickly as possible my areas of major concern and then figure out where I go next with it.

Thanks for everyone's points in this thread. I suppose comments in this issue thread will wind down soon which is also my desire. I will need to move on to other work, but also my strategy w.r.t. TypeScript, EMCAScript, modules, etc is being formed.

@shelby3 shelby3 mentioned this issue Sep 11, 2016
@spion
Copy link

spion commented Sep 11, 2016

@shelby3
Copy link
Author

shelby3 commented Sep 11, 2016

@spion wrote:

See https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

We've been discussing that document throughout this thread.

@shelby3
Copy link
Author

shelby3 commented Sep 12, 2016

All because of inflexible, purist design goals, we are unable to fix a type design error in JavaScript:

@shelby3 wrote:

In this case, I would argue it might be better to break the purist design goals of TypeScript, and introduce a new expression-level syntax for a string concatenation operator (e.g. # or ++) which is erased to + in the emitted output, but which only coerces to String (never from String to Number) or which never coerces. So then the programmer would have the option to use this new operator to get more clear compilation results and expression of intent. They would also have the option to continue to use + for string concatenation to retain the JavaScript semantics.

I realize my preference might not be shared with some (or even most) of the community and I would accept if they want to downvote this comment to indicate their disagreement with my preference. The downside of introducing new non-standard expression-level syntax is that it can become a pain point and incongruity with the rest of the ECMAScript universe; and with a myriad of transpiler syntax(es) then the ECMAScript ecosystem becomes ever more disjoint. However, TypeScript is introducing new syntax, so it is impossible to not have disjointedness form during competitive, free market experiments to improve a standard. I suppose the argument is to limit new syntax to outside of expression-level (and in TypeScript's case intended only for new syntax pertaining to erased typing) so at least expression-level remains consistent in the ECMAScript ecosystem. But in this case especially I would argue that since ECMAScript only has dynamic typing, they aren't likely to make it a priority to add a dedicated concatenation operator, so it seems to fall more into the responsibility of TypeScript. However I would also remain sympathetic to those who don't want to move too fast towards the best possible typing, and would instead prefer to retain ECMAScripts flaws for the sake of consistency in the ecosystem. I come at this from the perspective of hoping to influence standards by mass adoption in the free market, so I tend to avoid design-by-consensus to some extent although I try to consider this pragmatically. Microsoft (and Adobe) has (have) definitely learned the hard way (Silverlight, Flash, ActiveX in browser, IE proprietary APIs, etc) that proprietary syntax most often loses in the market place. I certainly don't consider design-by-isolation to be valid.

@kitsonk wrote:

This is more the domain of a linter, as the type system in this case is sound.

A linter isn't carried around with my code where ever it goes. It is not a fix to the design of the type system. That could be considered an advantage or disadvantage, depending on your perspective of the above.

@spion
Copy link

spion commented Sep 12, 2016

@shelby3 If by index properties you mean

let o = {
  ['prop']: 1
}

This is already in ES6. See object literal extensions

@spion
Copy link

spion commented Sep 12, 2016

The extensions that are most likely to be implemented in TypeScript next are existing ES6 features. Next are roughly the ECMAScript proposals on this list: https://github.com/tc39/proposals . Finally, some stage 0 proposals might also find their way in; they are here: https://github.com/tc39/proposals/blob/master/stage-0-proposals.md)

@shelby3
Copy link
Author

shelby3 commented Sep 12, 2016

@spion wrote:

This is already in ES6. See object literal extensions

Thank you. Even I have viewed that linked site many times (have a copy open in one of my browser tabs always), I hadn't paid attention to "object literal extensions".

@shelby3
Copy link
Author

shelby3 commented Sep 12, 2016

@spion wrote:

The extensions that are most likely to be implemented in TypeScript next are roughly ECMAScript proposals on this list: https://github.com/tc39/proposals (Some stage 0 proposals might also find their way in

Note that Private Fields is proposing a syntax which is different than the one TypeScript uses (and apparently some different semantics as well, so perhaps it is an orthogonal concept?). Someone from TypeScript should probably try to influence that proposal to adopt the private keyword instead of #. I think it is also very bad design to consume the very limited supply of operator symbols on the keyboard, for what can be served well with a keyword. They have a discussion thread about why they didn't use private.

Edit: note I have posted to that discussion there to propose how to avert the issue and be able to employ private normally with more idiomatic semantics.

@kitsonk
Copy link
Contributor

kitsonk commented Sep 12, 2016

Note that Private Fields is proposing a syntax which is different than the one TypeScript uses (and apparently some different semantics as well, so perhaps it is an orthogonal concept?). Someone from TypeScript should probably try to influence that proposal to adopt the private keyword instead of #.

This and this impact on TypeScript is being covered on #9950. Why are you dragging this issue off topic?

@shelby3
Copy link
Author

shelby3 commented Sep 12, 2016

@kitsonk wrote:

This and this impact on TypeScript is being covered on #9950.

Thanks for cross-referencing. Future discussion on that particular point should continue there.

Why are you dragging this issue off topic?

Because (if the design goals are off-topic then) you did in the 2nd comment of this thread, but I interpreted your comment to be on-topic.

And because narrowing by-example relevant to our discussion derived from your linked comment above (example of how TypeScript violated its own design goals and created syntax that could be rendered deprecated by the coming changes to ES) caused you to cross-reference to the more specific issue above. ;)

Certainly you don't expect every commentator here to live in this TypeScript Issues their entire days and nights and be entirely aware of every issue thread. Kudos to you for doing that for us.

The implied example is to point out that the design goals aren't 100% steadfast and leak-proof. They are apparently guidelines, not infallible absolutism.

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Sep 12, 2016

I want to elucidate the "syntax" thing since there is a distinction that has not been made clear.

TypeScript has added syntax "holes" where needed to express type system behavior. For example, type annotations in function parameters, or generics in function expressions, as you noted. This doesn't change the existing behavior of the JS, of course.

TS has also added some top-level declaration forms: enum, namespace, and so on. These are things which are legal in statement positions and do have runtime implications.

The thing TS hasn't done is added new behavioral expressions (those without ES Stage 1 or higher proposals):

Form Type System Runtime
Statement interface enum
Expression <Type>expr (none)

This is actually very consistent. Attractive things like the "elvis operator", implementing ** before it was ready, etc, have all been rejected due to being in the lower-right cell which we consider to be 100% the domain of the ES committee. And things like enum and namespace have to strongly justify their existence, both in terms of "syntactic ownership" of ES saying they won't do those things, and the value provided.

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

7 participants