Skip to content
This repository was archived by the owner on Jan 28, 2023. It is now read-only.

Normative: Switch syntax to ??: #23

Closed
wants to merge 1 commit into from
Closed

Conversation

littledan
Copy link
Member

Follows the conclusion of the discussion at
tc39/proposal-optional-chaining#34

Follows the conclusion of the discussion at
tc39/proposal-optional-chaining#34
@littledan
Copy link
Member Author

Note the parallel change for optional chaining at tc39/proposal-optional-chaining#48 .

@hax
Copy link
Member

hax commented Feb 26, 2018

Too many ?... and ??. looks too close to ??: which very harmful to readability...

const city = staff??.company??.address??.city??:defaultCity;

PS. Compare to my syntax suggestion:

const city = staff!.company!.address!.country??defaultCity;

@ljharb
Copy link
Member

ljharb commented Feb 26, 2018

Using !. suggests to me either a boolean operation, or conflicts with Ruby/Rails idioms meaning “mutates” or “throws”; separately, as I’ve already pointed out, ![ and !( conflict with existing meanings.

@hax
Copy link
Member

hax commented Feb 26, 2018

@ljharb As I said before, TS already use ! as non-null assertion, a!.b, a![b], a!() are all valid in TS which compatible with ES2017, so I have no idea how "![ and !( conflict with existing meanings".

@ljharb
Copy link
Member

ljharb commented Feb 26, 2018

@hax existing meanings in JS, and other languages. That TS chose that meaning does not mean it's idiomatic for JS, nor that it would be consistent with non-JS non-TS languages.

Separately, "assertion" usually means "throws if it fails" - which is the opposite of with optional chaining does.

@littledan
Copy link
Member Author

@ljharb If this is a widely used feature in TypeScript, it could be a real problem for adoption here, which we could avoid with the strategy in this PR. This isn't the only language community where grammar intersection with different languages comes up; for example, C++ has to worry about Objective-C grammar when considering its evolution.

@ljharb
Copy link
Member

ljharb commented Feb 26, 2018

@littledan makes complete sense; i'm mostly trying to argue that !. isn't a good choice regardless, such that I think its conflict with TypeScript can be made irrelevant.

@hax
Copy link
Member

hax commented Feb 26, 2018

@ljharb
If the original proposed a?.b can be seen as a == null ? null : a.b and not "conflict", then a!.b also can be seen as a != null ? a.b : null which not "conflict".

And if you not consider TS idioms, why consider Ruby/Rails or any other languages which more far from JS?

If this is a widely used feature in TypeScript, it could be a real problem for adoption here

@littledan See tc39/proposal-optional-chaining#34 (comment)

js-choi added a commit to tc39/proposal-smart-pipelines that referenced this pull request Feb 26, 2018
@ScottRudiger
Copy link

@hax @littledan @ljharb

And if you not consider TS idioms, why consider Ruby/Rails or any other languages which more far from JS?

If this is a widely used feature in TypeScript, it could be a real problem for adoption here

From the (hypothetical) perspective of someone who's learning JavaScript after coming from another language, I would think that

Ruby/Rails --> JavaScript is more common than TypeScript --> JavaScript

In the case of TypeScript, I would think most find themselves following the path:
JavaScript (fundamentals, at least) --> TypeScript

so there is a kind of difference, in my opinion.

Further, (if perhaps more controversial)TypeScript is a superset of JavaScript so in the case of the two doubly-implementing the same feature (but with different syntax) I would think it's more logical for TypeScript to eventually deprecate said feature in a breaking update.

@littledan
Copy link
Member Author

I'm not sure if it's feasible for TypeScript to make breaking updates these days. cc @rbuckton @DanielRosenwasser

@hax
Copy link
Member

hax commented Feb 27, 2018

@ScottRudiger
I see it in another way. In my opinion, we should consider language idioms in this order:

  1. JavaScript itself
  2. TypeScript, ActionScript, flow, or any JavaScript dialects or extensions
  3. CoffeeScript, LiveScript, or any languages mainly based on JS semantics and set JS as the first compiling target
  4. Python, C#, Groovy, Swift, PHP, Ruby... and any other languages

IMO, it begin at the wrong end to consider the new comers from Ruby/Rails prior to the core users from TS. NOTE: all TS users are actually JS heavy users!

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Feb 27, 2018

To start off, I'd like to clarify - TypeScript's postfix ! semantics actually differ enough in this respect that it would be a problem. It doesn't correspond to a "carry over undefined (and/or null) if the left side of the ! is null/undefined". In fact, it outright removes the null/undefined from the type of the LHS.

But apart from that, I have to agree that I don't feel the ! conveys enough about the optional chaining. I'm not so hot on ?? either, but I'll have to discuss with others on my team.

@hax
Copy link
Member

hax commented Feb 27, 2018

@DanielRosenwasser @littledan About repurpose!, you could check my original post: tc39/proposal-optional-chaining#34 (comment)

To recap: change non-null assertion to !!(same as Kotlin) and use ! for non-null chaining is not a "very breaking" change for TS.

Anyway, in this thread I just want to argue the problem of differentiating ??. and ??: . I only use !. as a comparison, but other alternatives also apply. Let's continue discussion in tc39/proposal-optional-chaining#34 .

@DanielRosenwasser
Copy link
Member

is not a "very breaking" change for TS.

It's definitely a breaking change. 😄 For example, changing the semantics to null-propagation means that you could absolutely introduce a type error under in the expression a!.b.c which could break a user's build.

Just to clarify, consider the following:

declare let a: null | {
  b: {
    c: number
  }
};

// Non-null assertion: has type `number` 
a!.b.c;

// Rough equivalent of the null-propagation `a?.b.c`; is a type error
(a != null ? a.b : a).c;

@hax
Copy link
Member

hax commented Feb 28, 2018

@DanielRosenwasser
Yes it will introduce compile-time type errors if strict null check is enabled (I already point out this in the original post). But by default ( noEmitOnError default to false) TS compiler will still emit the code, and the runtime result is same -- if a.b.c (current compile output) works then (a != null ? a.b : a).c will also work -- because T is the subtype of T | null | undefined.

That's what I mean "not very breaking". (Forgive my poor english if I express the wrong meaning)

And, it's very easy to migrate old ! to !!, you even can do it now, because !! is valid and have the same result now. So I can imagine if ! proposal was accepted, it's very easy to provide a migration tool in next TS release :-)

@0rvar
Copy link

0rvar commented Mar 29, 2019

I do not like these changes. Can someone summarise the problem with the current syntax?

@claudepache
Copy link

@0rvar This change is required if tc39/proposal-optional-chaining#48 is adopted, because otherwise a??[b] would become ambiguous. (But at this point, there is not much chance that tc39/proposal-optional-chaining#48 will be adopted, and therefore neither the present PR.)

@littledan
Copy link
Member Author

Closing per #23 (comment)

@littledan littledan closed this Apr 5, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants