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
But that would produce invalid results. If selectedFunc would be an intersection, then it would be appear as an overloaded function, even tho it's not.
For example if you manually force an intersection:
The compiler will assume it calls Func1, because that's what the obj parameter matches to. But it actually calls Func2 which gets an invalid object passed along.
Is this issue saying that selectedFunc should be of type typeof Func1 because the condition in the ternary is statically known to be true? If so, that is working as intended as per #14206. As far as I know, the type of x ? y : z is always (equivalent to) typeof y | typeof z regardless of whether x is known to be truthy or falsy.
Or is this issue saying that selectedFunc should be of type typeof Func1 | typeof Func2, but that you should be able to call it with a Func1Options | Func2Options argument? If so, then this is working as intended, as implemented in #29011, which is a partial fix for #7294. It is not safe for a union of functions to accept a union of arguments, because function arguments are contravariant. Consider the following code:
At runtime, selectedFunc may turn out to be Func1. Inside the selectedFunc({age: 20}) call, options.name.toUpperCase() will end up trying to call a method on undefined, and you will get a runtime error. It's not safe. Unless you can narrow selectedFunc to either typeof Func1 or typeof Func2, the only safe thing you can pass it as an argument is Func1Options & Func2Options. That way you know no matter which function it turns out to be, it will have an argument that meets its needs.
Reacted by Bruce Pascoe, Max Rukomoynikov and Ryan Cavanaugh
Is this issue saying that selectedFunc should be of type typeof Func1 because the condition in the ternary is statically known to be true? If so, that is working as intended as per #14206. As far as I know, the type of x ? y : z is always (equivalent to) typeof y | typeof z regardless of whether x is known to be truthy or falsy.
Or is this issue saying that selectedFunc should be of type typeof Func1 | typeof Func2, but that you should be able to call it with a Func1Options | Func2Options argument? If so, then this is working as intended, as implemented in #29011, which is a partial fix for #7294. It is not safe for a union of functions to accept a union of arguments, because function arguments are contravariant. Consider the following code:
At runtime, selectedFunc may turn out to be Func1. Inside the selectedFunc({age: 20}) call, options.name.toUpperCase() will end up trying to call a method on undefined, and you will get a runtime error. It's not safe. Unless you can narrow selectedFunc to either typeof Func1 or typeof Func2, the only safe thing you can pass it as an argument is Func1Options & Func2Options. That way you know no matter which function it turns out to be, it will have an argument that meets its needs.
Thank you, for description. Now I understand kind of philosophy of ts,
Activity
MartinJohns commentedon Aug 24, 2019
But that would produce invalid results. If
selectedFuncwould be an intersection, then it would be appear as an overloaded function, even tho it's not.For example if you manually force an intersection:
The compiler will assume it calls
Func1, because that's what theobjparameter matches to. But it actually callsFunc2which gets an invalid object passed along.jcalz commentedon Aug 24, 2019
Is this issue saying that
selectedFuncshould be of typetypeof Func1because the condition in the ternary is statically known to betrue? If so, that is working as intended as per #14206. As far as I know, the type ofx ? y : zis always (equivalent to)typeof y | typeof zregardless of whetherxis known to be truthy or falsy.Or is this issue saying that
selectedFuncshould be of typetypeof Func1 | typeof Func2, but that you should be able to call it with aFunc1Options | Func2Optionsargument? If so, then this is working as intended, as implemented in #29011, which is a partial fix for #7294. It is not safe for a union of functions to accept a union of arguments, because function arguments are contravariant. Consider the following code:At runtime,
selectedFuncmay turn out to beFunc1. Inside theselectedFunc({age: 20})call,options.name.toUpperCase()will end up trying to call a method onundefined, and you will get a runtime error. It's not safe. Unless you can narrowselectedFuncto eithertypeof Func1ortypeof Func2, the only safe thing you can pass it as an argument isFunc1Options & Func2Options. That way you know no matter which function it turns out to be, it will have an argument that meets its needs.jack-williams commentedon Aug 24, 2019
Martin Johns (@MartinJohns)’s comment shows why the current behaviour is the correct one.
More details can be found here: #29011
Rukomoynikov commentedon Aug 25, 2019
Thank you, for description. Now I understand kind of philosophy of ts,