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
{{ message }}
Repository navigation
Inconsistent String Literal Type Propagation #15271
The type of foo and baz are both "MY_TYPE" as expected.
However using this strEnum function as described here which, based on my understanding, should be doing the same thing as the above code, results in something different:
This is working as intended. In the call strEnum(["MY_TYPE"]), the "MY_TYPE" literal has a widening literal type (see #11126) because it was never given an explicit type through a type annotation or a type assertion. You get the desired result if you explicitly assert a type:
constmyTypeEnum=strEnum(["MY_TYPE"as"MY_TYPE"])
Reacted by Herrington Darkholme, Matt Nedrich and Drew Colthorp
I'm left a bit surprised by the type widening here. In a project using react-redux, I'm having to declare types that I would expect the compiler to be able to infer.
In all of the following examples, I would expect the code to compile. However, there are many where it does not:
// Example 1// DOES NOT compileinterfaceMyAction{type: 'MY_ACTION'}constaction={type: 'MY_ACTION'}constreassignment: MyAction=action;// Example 2// DOES NOT compileconstMY_ACTION='MY_ACTION';interfaceMyAction{type: typeofMY_ACTION}constaction={type: MY_ACTION}constreassignment: MyAction=action;// Example 3// DOES compileconstMY_ACTION: 'MY_ACTION'='MY_ACTION';interfaceMyAction{type: typeofMY_ACTION}constaction={type: MY_ACTION}constreassignment: MyAction=action;// Example 4// DOES compileconstMY_ACTION='MY_ACTION';interfaceMyAction{type: typeofMY_ACTION}constaction: MyAction={type: MY_ACTION}constreassignment: MyAction=action;
Are all these situations truly as intended? Is this because the object is not guaranteed to be immutable? If that's the case, the widening difference between example 2 and 3 is throwing me off.
Hmm... that case certainly makes sense. I don't know if it's prohibitively expensive to do this, but could the compiler avoid widening the type within a certain scope if it can guarantee that an object is never mutated? Though even in that case
Another possible alternative here that might be nice would be to introduce a keyword in the type layer called literal.
Activity
ahejlsberg commentedon Apr 19, 2017
This is working as intended. In the call
strEnum(["MY_TYPE"]), the"MY_TYPE"literal has a widening literal type (see #11126) because it was never given an explicit type through a type annotation or a type assertion. You get the desired result if you explicitly assert a type:bilalq commentedon Apr 20, 2017
I'm left a bit surprised by the type widening here. In a project using react-redux, I'm having to declare types that I would expect the compiler to be able to infer.
In all of the following examples, I would expect the code to compile. However, there are many where it does not:
Are all these situations truly as intended? Is this because the object is not guaranteed to be immutable? If that's the case, the widening difference between example 2 and 3 is throwing me off.
RyanCavanaugh commentedon Apr 20, 2017
Consider a slight variant:
Without explicit intent, it's very tricky to infer literal types. You can quickly find yourself issuing errors on code that is extremely unsuspicious.
mattnedrich commentedon Apr 20, 2017
Thanks for the clarification! I'm going to close.
bilalq commentedon Apr 20, 2017
Hmm... that case certainly makes sense. I don't know if it's prohibitively expensive to do this, but could the compiler avoid widening the type within a certain scope if it can guarantee that an object is never mutated? Though even in that case
Another possible alternative here that might be nice would be to introduce a keyword in the type layer called
literal.It expresses intent clearly, and avoids the triple repetition that we currently have to do:
Would this be a proposal that might be considered? Or are there downsides to this?