-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
To/from assignability is too strict of a check for comparison and other operations #5300
Comments
so what is the proposal? for logical operators to allow operands with union types if at least one of their constituents is assignable to the other operand's type? |
@mhegazy yup, that's more or less what I had in mind. |
Is it possible that contextual typing is not a sufficient trigger for string literal types? In other words, it seems like the string "boolean" should intuitively be a string literal type and then it would just be assignable to the union type. This is an argument in favor of the widening approach for deciding whether to type a string literal as a string literal versus as |
It's still a tough call. As I mentioned in the pull request, widening the way we do now with On the other hand, contextual typing is very close to what you want. Maybe what we want is something that's a step above contextual typing - call it contextually relevant typing. The idea would be "right now, I am talking about this domain of types", as opposed to contextual typing which originally was just meant to say "this must be the type". If a string literal type is contextually relevant for a string literal, then its type is a string literal type. You could say a switch statement makes the type of its expression contextually relevant to its case clauses, or that somehow each side of a comparison operator's type is contextually relevant for the other side (though I don't know how you prioritize one side over the other). Honestly, this is me extremely exhausted and brainstorming at 1 in the morning. 😄 Anyhow, I think the shortcomings described here are part of a larger issue than string literal types though. |
I think contextual typing is pretty much what you are calling "contextually relevant typing". It does not say, "this must be the type". That is assignability saying that. I don't think the null / undefined properties are an issue here. If I understand correctly, you are saying that the following will fail: var s: "hello";
var s1 = "hello";
s = s1; // not assignable But that failure happens with contextual typing as well. I think the biggest issue with the widening approach is that types are widened after type argument inference, which is an issue we have discussed before. It makes it so that any string literals that get inferred are automatically widened to string, which is a little unfortunate. |
We have seen this with tuples, and to some extent with optional properties. For every kind of expression in the language that can have multiple types in different situations (array literals, string literals, null and undefined), the question always comes up about how to distinguish the two possible types. And the candidate answers are always contextual typing and widening. And there does not seem to be a pattern as to which one is picked. Ideally, the language would have a duality, where contextual typing and widening had mutually exclusive syntactic contexts. So the following two properties are desirable:
If these were true, then the decision of contextual typing versus widening would only matter in contexts where there is no contextual typing and no widening (like comparison operators). And you could always make the decision based on what you want in these cases, rather than having to worry about breaking type argument inference or function return types. Another thought: The widening approach is weird because of cases like this: var s: "hello";
var s1 = s; What is the type of s1 with the widening approach? It is string I guess. Widening is an operation defined on types, though in spirit we often want to apply it to expressions (except in type argument inference). To get the type "hello" for s1 here with the widening approach, it would really require separating the notion of widening types from widening expressions. And that would be an annoying complexity. So I think it would be a very nice long term goal to achieve the two properties I mentioned above. In the mean time, I think your heuristic about the union type constituents will be good in order to capture the notion of "related enough for comparison". |
@DanielRosenwasser is this fixed by the comparability relation? |
@RyanCavanaugh yes, it is fixed by #5517 and #12202 |
This can be seen as the dual of #5156 and an extension of #1447. While the former seeked to limit what could be compared, this issue seeks to be more permissive.
Currently, the following causes an error:
So while
y
andz
are bothI2
s at runtime, we restrict the two from comparison.This is especially troublesome with my work on string literal types. In trying to use string literal types on our own codebase, I encountered something like the following:
Of note: because I use the contextual type to inform string literal types,
"string"
in thecase
clause remains having thestring
type.The text was updated successfully, but these errors were encountered: