-
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
Expression produces a union type that is too complex to represent #53234
Comments
If you were close to hitting the limit before and inference slightly changed in a generally non-observable way (say, to fix a bug), you might end up hitting the limit. Encountering the error is not a per se defect; we'd need a minimal example of this being a false positive to investigate further. |
@RyanCavanaugh Thanks for the explanation. Deep down, this code should be quite far from the limit; it is modelling CSS properties and the types of their values, which shouldn't be anywhere near 100,000 🤔 OTOH, there is a map of functions whose strict type gets lost and that could cause a multiplication of cardinals of unions when we retrieve stuff, leading to the explosion 💥 |
@RyanCavanaugh I've managed to extract a MNWE 🎉 Interestingly, my real code does build in TS 4.8.4, but this simplified version breaks all the way back to 4.1.5 (in 4.0.5, another error pops up preventing this one…) I'm a bit surprised by that given how much of a simplification I did on the way (notably shrinking down the union quite a lot…) |
We've encountered this too when trying to migrate to from Typescript v4 to v5. Possible duplicate of #52459. |
👋 Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript. Issue body code block by @Jym77 ❌ Failed: -
Historical Information
|
Investigating the minimal repro posted here, it doesn't seem like this is a bug. What happens is that, when we try to compute the type of |
hi @gabritto thanks for the explanation. Following the thread as we have a similar issue do you know why this could have appeared with typescript 5 ? could it be related to the fact that enums are now "considered" unions ? thanks! |
Honestly, it could be a number of different things, I can't tell without looking at an example. |
Here's a simplified repro: type Box<T> = { value: T };
type Func<T> = (x: T) => T;
declare const f1: Func<Box<10>> | Func<Box<11>>;
declare const f2:
Func<Box<10> | Box<11> | Box<12> | Box<13> | Box<14> | Box<15> | Box<16> | Box<17> | Box<18> | Box<19>> |
Func<Box<20> | Box<21> | Box<22> | Box<23> | Box<24> | Box<25> | Box<26> | Box<27> | Box<28> | Box<29>> |
Func<Box<30> | Box<31> | Box<32> | Box<33> | Box<34> | Box<35> | Box<36> | Box<37> | Box<38> | Box<39>> |
Func<Box<40> | Box<41> | Box<42> | Box<43> | Box<44> | Box<45> | Box<46> | Box<47> | Box<48> | Box<49>> |
Func<Box<50> | Box<51> | Box<52> | Box<53> | Box<54> | Box<55> | Box<56> | Box<57> | Box<58> | Box<59>>;
declare const x: Box<10>;
f1(x); // Error: Argument of type 'Box<10>' is not assignable to parameter of type 'never'.
f2(x); // Error: Expression produces a union type that is too complex to represent. As The |
So, ultimately, I'd say this is working as intended. |
I've been doing some digging, and it seems we've run into this problem before, of producing the "Expression produces a union type that is too complex to represent" for an intersection that would reduce to It seems like this is something that comes up for people, given there are multiple issues mentioning this same problem and more people mentioning running into these issues. So maybe we could do something about the cases where the complex type would reduce to |
On the other hand, the error message is also very vague and not that helpful, it seems to me that people are surprised when their union of 50 or 200 elements becomes a union with more than 100k elements. But I don't really know what we could do about it. For instance, we could try to display the type somehow, but I'm not sure if displaying the type would help people in figuring out why we were trying to intersect a bunch of unions in the first place... |
Interesting that we already have a PR in this area. We should bring it up to date and reevaluate it. In an ideal world we'd quickly recognize intersections of object types that turn into |
@gabritto Thanks for looking into this. I do agree that the error message was confusing, but I also fail to see how it could be made much better 🤔 In this case, this also plays on the subtlety of union of functions producing an intersection of paramters (due to contravariance). |
Digging a bit more into it… It seems my MWNE is actually incorrect in what it tries to do. function computed<N extends keyof Longhands>(
property: Longhands[N][1],
specified: Longhands[N][0]
) {
// error happens on this line
property.compute(specified);
} Now, the intention is to only call the function with a This lack of link is (I understand) what makes the union of functions explode (the type of Trying to enforce the link between both arguments: declare const longhands: Longhands;
function computed2<N extends keyof Longhands>(name: N) {
const foo = longhands[name];
// error happens on this line
foo[1].compute(foo[0]);
} I still get the same problem. But this time, it feels like But I guess this leads to a question… Is there a way to type that function in a way that keeps the link between This sort of boils down to the fact that function computed3(name: "font-family"): Family {
const foo = longhands[name];
return foo[1].compute(foo[0]);
} works like a charm, but function computed4<N extends "font-family" | "font-size">(name: N): Longhands[N][0] {
const foo = longhands[name];
// error happens on this line, foo[0] is not assignable to never
return foo[1].compute(foo[0]);
} breaks because Yet, in practice, |
You're right. The fact that we "explode" the type (i.e. we use a type parameter's constraint instead of the type parameter when resolving a type), and that we don't have a concept of " |
Typescript: 4.3.5: lodash.get funtion giving similar issue:
|
Bug Report
🔎 Search Terms
"Expression produces a union type that is too complex to represent"
(found #33130 which seems unrelated as it has been fixed)
🕗 Version & Regression Information
⏯ Playground Link
Example in Playground
💻 Code
Note: interestingly, I detected the error in the much more complex real code of Alfa where it only triggers in TS 4.9.3, but not in 4.8.4 🤔 I am not sure which simplification happens in my real code to keep the union smaller…
🙁 Actual behavior
The code produces the error:
🙂 Expected behavior
The union should be around 50 items big, far below the limit.
The text was updated successfully, but these errors were encountered: