-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Conditional Type Inference Bug in TS 5.x #58524
Comments
I could reduce the code even more. I believe it's minimal now. If I reduce the code more the problem goes away. |
Bisects to #55941 |
cc @Andarist - any thoughts? Should we revert that PR? |
@RyanCavanaugh hm, I'm not sure if this bisect result is correct. The referenced PR has been included since 5.4.0-dev.20231201 but the reported change is between 4.9 and 5.0 |
This changed between 5.0.0-dev.20221103 and 5.0.0-dev.20221108 . Looking at the commits within that range, I think the change was caused by #51405 |
I can confirm that #51405 changed this and it looks like working by design to me. Matching types are eliminated from inference here as per the comment close to that touched code: // We reduce intersection types unless they're simple combinations of object types. For example,
// when inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and This code tries to infer from source // { message: string; }
target // V & T This call is meant to return |
@Andarist Thanks for the investigation. I would use the unsimplified version, but if Typescript is going that direction, I can live with it. Do you think we can show a warning so this case wouldn't look like unexpected? |
Where you'd like to show a warning? Inference is incapable of raising warnings |
@Andarist is right - this code isn't really distinguishable from code that is removing We can't warn every time any possible thing happens. |
@RyanCavanaugh @Andarist As I see, my Why would this mean that I want to remove a random property from the type? I also tried this for curiosity (this is the same problem without functions): type Infer<T> = T extends Tidied<infer V> ? Tidied<V> : null
type Baz = Infer<Foo<{ message: string }>> This removes "name" from the type, however, not with So what's the difference between this: type Tidied<T> = T extends Bar<infer V> ? Tidied_Foo<T> : T;
type Tidied_Foo<T> = T extends Foo<infer V> ? T : T; and this: type Tidied<T> = T ? |
|
This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
@Andarist Thank you. I think I understand it now. For example, because type Infer<B> = B extends Foo<infer A> ? Foo<A> : null So here, typescript resolves to a seemingly random but correct type through its heuristics. Infer<{ bar: string }> = Foo<unknown> // ✅ correct
Infer<{ bar: string }> = Foo<{}> // ✅ correct
Infer<{ bar: string }> = Foo<{ bar: string }> // ✅ correct Similarly if the type is little bit more complex, e.g.: Infer<{ bar: { baz: string } }> = Foo<unknown> // ✅ correct
Infer<{ bar: { baz: string } }> = Foo<{}> // ✅ correct
Infer<{ bar: { baz: string } }> = Foo<{ baz: string }> // ✅ correct
Infer<{ bar: { baz: string } }> = Foo<{ baz: string, answer: 42 }> // ✅ correct, but unlikely Am I right? And, in that case, when can I rely on it? A more practical use case would be: type ArrayItem<T> = T extends Array<infer V> ? V : never I would expect that I get |
🔎 Search Terms
"Inference trims types", "inference excludes fields"
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?#code/C4TwDgpgBAYg9nAPAFQHxQLxQN5QHYCGAthAFxQBEAZghVAL5QBkUyA3AFCiRQBCBAJxTosuAG4EANgFcyrBpy7hoyAJYATVRHXDM8iAA9gEPOoDOfQYlV4qEAVABq6APysNW9QH14SNFHJ2JR41TW0fBF0sZChDY1MLX2tbeydXeUDFKmk8AGNgVTg8KBo-VAAKXIAjQI9tYQBKHA4oKAEIYGkBYurOeg4OXKKzYDaIM2lJYABGPVLy3EIScmpaABooEjMzAgBzOQoACQgQAEI6RgJEyNwtnf3yEYEbXYZUBs52ianpgDoliBsKAAemBUAAogIBHABOQAArQyACUBQADkANRUHUcHG+Dgo0MqhGUCKUG40FRt3G9zkTxeQPoqIGQzwxK+k2AACY5ggFvhiAdShQNnc9gdjmcLh8OOyppz-gKgaCoAA5OCxKEwoA
💻 Code
🙁 Actual behavior
🙂 Expected behavior
no type error
Additional information about the issue
I was working on my project Cuple. I found a weird bug. I spent my day to provide a small minimal example. I have a type
Tidied
which is used to make a developer friendly type from the complex built response types. It worked well for some cases but it doesn't work for the case that I provided. The original version makes more sense.The text was updated successfully, but these errors were encountered: