-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Inconsistent String Literal Type Propagation #15271
Comments
This is working as intended. In the call const myTypeEnum = strEnum(["MY_TYPE" as "MY_TYPE"]) |
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 compile
interface MyAction {
type: 'MY_ACTION'
}
const action = {
type: 'MY_ACTION'
}
const reassignment: MyAction = action;
// Example 2
// DOES NOT compile
const MY_ACTION = 'MY_ACTION';
interface MyAction {
type: typeof MY_ACTION
}
const action = {
type: MY_ACTION
}
const reassignment: MyAction = action;
// Example 3
// DOES compile
const MY_ACTION: 'MY_ACTION' = 'MY_ACTION';
interface MyAction {
type: typeof MY_ACTION
}
const action = {
type: MY_ACTION
}
const reassignment: MyAction = action;
// Example 4
// DOES compile
const MY_ACTION = 'MY_ACTION';
interface MyAction {
type: typeof MY_ACTION
}
const action: MyAction = {
type: MY_ACTION
}
const reassignment: 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. |
Consider a slight variant: const DEFAULT_COLOR = 'RED';
const style = {
background: DEFAULT_COLOR;
};
if (user.useNeatBackground) {
// Error? Cannot convert "BLUE" to "RED" ?
style.background = 'BLUE';
} Without explicit intent, it's very tricky to infer literal types. You can quickly find yourself issuing errors on code that is extremely unsuspicious. |
Thanks for the clarification! I'm going to close. |
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 const SUBMIT_COMMENT_SUCCEEDED: literal = 'SUBMIT_COMMENT_SUCCEEDED'; It expresses intent clearly, and avoids the triple repetition that we currently have to do: const SUBMIT_COMMENT_SUCCEEDED: 'SUBMIT_COMMENT_SUCCEEDED' = 'SUBMIT_COMMENT_SUCCEEDED'; Would this be a proposal that might be considered? Or are there downsides to this? |
TypeScript Version: 2.3.0 RC
I'm observing some strange type behavior. Consider the following snippet.
The type of
foo
andbaz
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:Here,
foo
is detected to be type"MY_TYPE"
, butbaz
is recognized as typestring
Am I doing something wrong? Is this expected behavior?
The text was updated successfully, but these errors were encountered: