Closed littledan closed 5 years ago
Note the parallel change for optional chaining at https://github.com/tc39/proposal-optional-chaining/pull/48 .
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;
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.
@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".
@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.
@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.
@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.
@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 https://github.com/tc39/proposal-optional-chaining/issues/34#issuecomment-350641176
@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.
I'm not sure if it's feasible for TypeScript to make breaking updates these days. cc @rbuckton @DanielRosenwasser
@ScottRudiger
I see it in another way. In my opinion, we should consider language idioms in this order:
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!
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.
@DanielRosenwasser @littledan About repurpose!
, you could check my original post: https://github.com/tc39/proposal-optional-chaining/issues/34#issuecomment-350641176
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 https://github.com/tc39/proposal-optional-chaining/issues/34 .
is not a "very breaking" change for TS.
It's definitely a breaking change. :smile: 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;
@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 :-)
I do not like these changes. Can someone summarise the problem with the current syntax?
@0rvar This change is required if https://github.com/tc39/proposal-optional-chaining/pull/48 is adopted, because otherwise a??[b]
would become ambiguous. (But at this point, there is not much chance that https://github.com/tc39/proposal-optional-chaining/pull/48 will be adopted, and therefore neither the present PR.)
Follows the conclusion of the discussion at https://github.com/tc39/proposal-optional-chaining/issues/34