-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
satisfies operator changes the type of an expression #55189
Comments
This is very specific to const foo = { prop: 'a' } satisfies { prop: 'a' | 'b' }
foo.prop = 'b' // error IIRC, there are some places in the compiler that special case |
Indeed, which is very unexpected behavior given the description of the feature. |
This is working as intended. The I suppose the issue here is that the release notes should have stated this. |
As those notes seem to be the only documentation on this feature, can they be updated? This was extremely surprising to run into |
EDIT: oh I see this has already been said here a minute or two ago As I said in another issue the wording of the description of |
Aside from the wording in the documentation making me think that the type of the variable wouldn't be affected by its initial value expression having After re-reading the original proposal thread for satisfies (and the feedback reset one) I was still confused, but time I noticed some stuff that prompted me to search for discussions about contextual typing unions. I stumbled on the following extremely relevant part of a comment:
I had no idea that was the case. As a side note, I was originally confused about why @Andarist was bringing up the union nature of booleans, but now it seems they were probably referring to this behavior. I've looked around a bit more but haven't been able to find a clear explanation of why contextually typing unions behaves this way. I've been reading and rereading stuff for a while though so my eyes may have glazed over a bit. If someone can provide more info about this or point me at some documentation1 or relevant discussion about this that I've missed I'd appreciate it. I suppose it's like a lot of things in the type system where it's something that makes possible the things that I do daily but that I've never noticed it because in other cases it's what I want. I found it totally surprising and unintuitive in this case though. I'm satisfied that this behavior isn't a bug now, so I'm closing the issue. It would be nice if folks would consider a documentation update to make it clearer that because 1. I didn't notice anything in the existing handbook page on type inference & contextual typing which covered this. |
@rimunroe Here's a good illustrative example: type Fooey = { foo: "foo" | "bar" };
const err = { foo: "qux" } satisfies Fooey; // error, good
const ok = { foo: "bar" } satisfies Fooey; // no error, also good Normally, properties in an object literal that are initialized with a primitive literal are widened when the type of the object is inferred; in this case, |
Welp I feel pretty dense. I was typing out a whole response about how it felt like this was just a subset of the problem I'd already shared and then suddenly your comment clicked and several other comments made more sense. Just to double check my understanding and in case anyone else comes across this in the future and struggled the same amount, is the following correct? In my specific case with boolean properties this feels confusing because the widened type you'd normally get, |
Also see #10676 for the basic rules for when literal types are and are not widened |
@rimunroe Yeah, that’s about the gist of it. Hypothetically, if |
Thank you so much to everyone for the patient explanations! |
Bug Report
Applying the
satisfies
operator to an expression can change the type of that expression.The release notes for the
satisfies
operator say the following:However, the type of the expression appears to be affected by the use of the operator.
This seems possibly related to #52394
🔎 Search Terms
satisfies, changes type, declaration
🕗 Version & Regression Information
Found in
This is the behavior in every version I tried, and I reviewed the FAQ for any entries related to declarations, expressions, narrowing, etc. and couldn't find anything
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
The type of
g
is{ a: true; }
whensatisfies Foo
is used, and{ a: boolean; }
if it's omitted.🙂 Expected behavior
The type of
g
is{ a: boolean; }
regardless of whethersatisfies Foo
is used.The text was updated successfully, but these errors were encountered: