You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Basically if you have a union type, narrowing down doesn't work if you are narrowing from unions with unions where some constituents of a union are subtypes of the other union.
For example, narrowing string | number to "hello" | number.
You end up with intersections today.
Cat & Mortgage seems unlikely, but it's indistinguishable from MixinA & MixinB.
Is that really common?
It happens in the compiler.
Whenever you have a non-discriminated union, things go wrong.
hasType exhibits some issues here, and the new behavior catches this.
But the new behavior explodes in types, is usually not the intent for many cases, and creates impossible branded literal types.
Why do we even use intersection types - can we do somethig more precise from the original example?
Necessary to work with object types.
A lot of user intent seems to indicate people think of types as closed.
Keeps coming up.
On a meta level, we need to think about this at a more holistic level, see what the interplay would be between negated types, closed types, etc.
Conclusion: we don't think we have any idea of how to cleanly solve the current problem. No action chosen. We may
Actually, I thought the trailing "We may" was very Yoda of you.
But the new behavior explodes in types, is usually not the intent for many cases, and creates impossible branded literal types.
I'm wondering for the sake of performance, whether it is useful to implement some overflow types in these situations such that they widen automatically as aliases of related basic types (eg string or any) if the explosion passes certain limits, thereby allowing them to collapse back to simpler type expressions.
At least then we might avoid performance issues and the programmer can see the underlying problem rather than a huge jumble of type combinations.
It's possible, but it could lead to a lot of unexpected results with behavior that's hard to predict. Also, we often don't know that an operation will cause the creation of many types until you perform the operation itself.
A lot of user intent seems to indicate people think of types as closed.
Excess property checking in object literals is a big contributor to this misconception, I’ve found. You would think the existence of intersection types (implying that overlap is possible) would clue people in, but alas...
To expand on the above point re: closed types, I think the error message for the excess property check is misleading:
interfaceFooBar{foo: string;bar: string;}letx: FooBar={foo: "pig",bar: "cow",baz: "ape",// error here};lettmp={foo: "pig",bar: "cow",baz: "ape",}lety: FooBar=tmp;// this is fine
The error message for the assignment to x is:
Type '{ foo: string; bar: string; baz: string; }' is not assignable to type 'FooBar'.
Object literal may only specify known properties, and 'baz' does not exist in type 'FooBar'.
"Not assignable" sounds like a blanket statement, but clearly it is assignable, since assigning the exact same type through tmp works; we've just made an exception for direct object literals in order to catch typos. To be fair, it does say "Object literal may only specify known properties", but the position of that text makes it appear like a footnote and easy to miss. Could we improve this error message to make it clearer that this is a special case and not the general statement about object assignability it looks like?
Bruce Pascoe (@fatcerberus) in a technical sense, the error message is correct - the fresh type '{ foo: string; bar: string; baz: string; }' is not assignable to type 'FooBar'.. But we don't show freshness in type printback, so it does seem wrong.
We could perhaps say something like
Type of object literal '{ foo: string; bar: string; baz: string; }' is not assignable to type 'FooBar'.
Object literal may only specify known properties, and 'baz' does not exist in type 'FooBar'.
I would probably just say Object literal '{ ... }' is not assignable to..., without mention of "type" at all. I'd want to make it very clear in the error message that this case only applies because the assignment is from a fresh object literal and is NOT a statement about structural typing in general.
I may look into doing the correct thing when all constituents of both the original type and the predicate type are primitives, since intersections of those are more intuitive and fall out when empty. On the other hand, I’m not sure if we want that kind of logical branching—maybe it’s better just to keep it in its current slightly wrong but consistent state.
Daniel Rosenwasser (@DanielRosenwasser) Can you point me to discussions on this topic? My intuition would be that an optional call feature would test for callability, not nullability. But I'd love to be convinced otherwise. FYI CoffeeScript's optional call feature tests for callability.
If optional call tests for callability, then based on the semantics of optional property access, you'd be propagating out undefined when you have an uncallable value. In other words, false?.() gives you undefined. That doesn't really seem like useful behavior to anyone I've discussed the feature with.
In my opinion it makes the most sense to keep optional call consistent with optional property access in that they both only propagate undefined from null/undefined.
Optional Chaining is Stage 3 now.
Is TS team going to implement optional chaining soon?
Reacted by David Babel, Alfredo Romero Morgen Wiria, Chris Bouchard, Benjamin Armstrong, XGHeaven, Gwanhyeong Lee, Matias Ribichich, Pavel Klimashkin, Hidemi Yukita, Andrew Wray and 2 more
Reacted by David Babel
Reacted by David Babel, Alfredo Romero Morgen Wiria, Chris Bouchard, HE Shi-Jun, Gwanhyeong Lee, Linus Unnebäck and Hidemi Yukita
Reacted by Geraldi Sutanto, David Babel, Frank Fang, HE Shi-Jun and Gwanhyeong Lee
Reacted by David Babel, Alfredo Romero Morgen Wiria, Chris Bouchard, HE Shi-Jun and Gwanhyeong Lee
It is not necessarily a good thing for TS. I don't mind TS to leave it alone (and break the "superset of ecmascript" promise). On the other hand, I'd be very upset if it were introduced in a lousy way.
I'm not saying optional chaining is bad. It is definitely good for JS due to its dynamic (unsafe) feature. That, may not the case in TS world, not without drawbacks.
Reacted by Trotyl Yu, Yuriy Grunin and Andrew Wray
As you said, TS is a superset of JavaScript, it does not have to miss futur JS features.
If it's not the best feature to come, it's still one, and people are not forced to use it.
But for me it's a great one.
As you said, TS is a superset of JavaScript, it does not have to miss futur JS features.
If it's not the best feature to come, it's still one, and people are not forced to use it.
But for me it's a great one.
I respect that. However don't you think the PL guys should consider more than 'people are not forced to use it'? Isn't any feature like that?
Here's a simple example:
interfaceSomething{p1: Other}interfaceOther{p2: string}lets: Something= ...
// are you going to let me write this? // Either way, you are breaking something: the typing or the superset thing s.p1? .p2?
I'd believe the reality would be much more complicated, as this note says.
xiuxiuxiu (@noru) As I understand, TS should not allow you write s.p1?.p2 because s.p1 is never nullish. It is only allowed if the interface Something is:
drop the runtime null-safe guarantee that js provides.
I'm not sure I understand what you mean. Do you mean s.p1 could be nullish in JS runtime even TS never allow it in compile time? It's possible anyway, but I don't think it's a good reason to abuse ?. to write everything like a?.b?.c?.d?.e.
But I don't think it's a good reason to abuse ?. to write everything like a?.b?.c?.d?.e.
Again, I agree. But I don't see means to prevent such abuse. That's why I said I don't mind not having it in TS when types already solved 80% of my problems.
I think the question is, how to enable full support of optional chaining without hurt the existing types. It may be a mission impossible...
Activity
hax commentedon Jun 28, 2019
Is TS team going to implement optional chaining soon? (Maybe here is the wrong place to ask, but related issues have been locked :-)
fatcerberus commentedon Jun 28, 2019
Well? You may... what? Don't leave us hanging here! 😄
HE Shi-Jun (@hax) Optional chaining is Stage 2. TS typically doesn't implement proposed syntax until it hits Stage 3.
DanielRosenwasser commentedon Jun 28, 2019
Ugh, it's been a week but I assume it's probably just "revisit if we come up with other ideas." Andrew Branch (@andrewbranch)?
poseidonCore commentedon Jun 29, 2019
Actually, I thought the trailing "We may" was very Yoda of you.
I'm wondering for the sake of performance, whether it is useful to implement some
overflowtypes in these situations such that they widen automatically as aliases of related basic types (egstringorany) if the explosion passes certain limits, thereby allowing them to collapse back to simpler type expressions.At least then we might avoid performance issues and the programmer can see the underlying problem rather than a huge jumble of type combinations.
DanielRosenwasser commentedon Jun 29, 2019
It's possible, but it could lead to a lot of unexpected results with behavior that's hard to predict. Also, we often don't know that an operation will cause the creation of many types until you perform the operation itself.
fatcerberus commentedon Jun 29, 2019
Excess property checking in object literals is a big contributor to this misconception, I’ve found. You would think the existence of intersection types (implying that overlap is possible) would clue people in, but alas...
fatcerberus commentedon Jul 1, 2019
To expand on the above point re: closed types, I think the error message for the excess property check is misleading:
The error message for the assignment to
xis:"Not assignable" sounds like a blanket statement, but clearly it is assignable, since assigning the exact same type through
tmpworks; we've just made an exception for direct object literals in order to catch typos. To be fair, it does say "Object literal may only specify known properties", but the position of that text makes it appear like a footnote and easy to miss. Could we improve this error message to make it clearer that this is a special case and not the general statement about object assignability it looks like?RyanCavanaugh commentedon Jul 1, 2019
Bruce Pascoe (@fatcerberus) in a technical sense, the error message is correct - the fresh type
'{ foo: string; bar: string; baz: string; }' is not assignable to type 'FooBar'.. But we don't show freshness in type printback, so it does seem wrong.We could perhaps say something like
fatcerberus commentedon Jul 1, 2019
I would probably just say
Object literal '{ ... }' is not assignable to..., without mention of "type" at all. I'd want to make it very clear in the error message that this case only applies because the assignment is from a fresh object literal and is NOT a statement about structural typing in general.andrewbranch commentedon Jul 1, 2019
Sounds right to me 😄
Or possibly it was referring to what I posted in the issue?
michaelficarra commentedon Jul 12, 2019
Daniel Rosenwasser (@DanielRosenwasser) Can you point me to discussions on this topic? My intuition would be that an optional call feature would test for callability, not nullability. But I'd love to be convinced otherwise. FYI CoffeeScript's optional call feature tests for callability.
DanielRosenwasser commentedon Jul 12, 2019
If optional call tests for callability, then based on the semantics of optional property access, you'd be propagating out
undefinedwhen you have an uncallable value. In other words,false?.()gives youundefined. That doesn't really seem like useful behavior to anyone I've discussed the feature with.In my opinion it makes the most sense to keep optional call consistent with optional property access in that they both only propagate
undefinedfromnull/undefined.ppjjzz commentedon Jul 26, 2019
Optional Chaining is Stage 3 now.
Is TS team going to implement optional chaining soon?
DavidBabel commentedon Jul 26, 2019
pandaJ (@ppjjzz) you was faster than me :)
Here is the reference : https://github.com/tc39/proposal-optional-chaining
Can't wait to see it in typescript.
noru commentedon Jul 29, 2019
It is not necessarily a good thing for TS. I don't mind TS to leave it alone (and break the "superset of ecmascript" promise). On the other hand, I'd be very upset if it were introduced in a lousy way.
I'm not saying
optional chainingis bad. It is definitely good for JS due to its dynamic (unsafe) feature. That, may not the case in TS world, not without drawbacks.DavidBabel commentedon Jul 30, 2019
As you said, TS is a superset of JavaScript, it does not have to miss futur JS features.
If it's not the best feature to come, it's still one, and people are not forced to use it.
But for me it's a great one.
noru commentedon Jul 31, 2019
I respect that. However don't you think the PL guys should consider more than 'people are not forced to use it'? Isn't any feature like that?
Here's a simple example:
I'd believe the reality would be much more complicated, as this note says.
hax commentedon Jul 31, 2019
xiuxiuxiu (@noru) As I understand, TS should not allow you write
s.p1?.p2becauses.p1is never nullish. It is only allowed if the interfaceSomethingis:noru commentedon Jul 31, 2019
Yeah I'd like to see that too. But therefore TS goes separate way with js and drop the runtime null-safe guarantee that js provides.
hax commentedon Jul 31, 2019
I'm not sure I understand what you mean. Do you mean
s.p1could be nullish in JS runtime even TS never allow it in compile time? It's possible anyway, but I don't think it's a good reason to abuse?.to write everything likea?.b?.c?.d?.e.noru commentedon Jul 31, 2019
Again, I agree. But I don't see means to prevent such abuse. That's why I said I don't mind not having it in TS when types already solved 80% of my problems.
I think the question is, how to enable full support of
optional chainingwithout hurt the existing types. It may be a mission impossible...FrankFang commentedon Aug 1, 2019
TypeScript could give tips for such abuse I believe. xiuxiuxiu (@noru)
w0rp commentedon Aug 5, 2019
Optional chaining is going to be great, and I look forward to seeing in TypeScript. It will simplify a ton of the code I write in a team every day.
fr0 commentedon Aug 9, 2019
Definitely. Is it fair to ask whether it is reasonable for us to expect this in 3.6? Or is that too soon?
weswigham commentedon Aug 9, 2019
Too soon. We cut the 3.6 beta 4 weeks ago, and the RC is in the next few days.