Repository navigation
Expression produces a union type that is too complex to represent #33130
Description
Activity
sandersn commented
on Aug 29, 2019 MemberMore actionsThis error was added intentionally, so it’s likely to be by design, but we should take a look at the code to confirm.
- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Aug 29, 2019 Righto, so
nameis a union of the 52 (! that API is big) keys in the language service object, whileinterceptis aPartial<LanguageService>, which means every property is a union of it's actual type (often a signature-containing object) andundefined. When we're assigning to this, we produce an intersection like -((() => void) | undefined) & (((fileName: string) => DiagnosticWithLocation[]) | undefined) & (((fileName: string) => Diagnostic[]) | undefined)and so on, which we then normalize (so we distribute to lift the union to the outside). This normalization spreads the types, so you get something like(() => void) & undefined & undefined | (() => void) & ((fileName: string) => DiagnosticWithLocation[]) & undefined | (() => void) & ((fileName: string) => DiagnosticWithLocation[]) & ((fileName: string) => Diagnostic[])and so on, enumerating every possible combination of the input types. Without any kind of simplification taken into account, for an intersection of 52 unions of 2 elements, we would need to produce 4.5e15 resulting top-level union elements. That's way too many. We calculate that number in advance, see that it's greater than our cap of 100000, and issue the error in the OP.Now, this specific case, when we're distributing a ton of unions, all of which contain
undefined, I think we could preemptively simplify to greatly reduce that number, sinceundefinedcan't be subtyped under our current rules (undefinedintersected with pretty much anything else is alwaysnever). I posited as much when we originally added the limit, and it looks like we do have reason to do so. It's probably worth noting that what I'm thinking of'll only help situations where every input is a union containingundefined(and maybenull), though. :SReacted by AnyhowStep, John Nistico, DemoorBug, Mykyta Matushyn, Viet Ta, Kostayne, Abhishek Sharma and Gustavo Henke- addedBugA bug in TypeScriptA bug in TypeScriptDomain: PerformanceReports of unusually slow behaviorReports of unusually slow behaviorand removedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Aug 29, 2019 My question: if normalization was really producing that many types, why did this work before instead of, you know, causing OoM?
Because the type simplifies massively upon construction -
undefinedandnull, intersected with anything, are justnever, so for every combination we made, we'd just getnever, then discard that element and move on (which'd chew thru compute time but not really memory). Or that's what we would have done, had we been making the type prior to 3.5 - prior to 3.5 we were just not making the constraint correctly and unsoundly checked against a union of unions, so it never came up.- locked as resolved and limited conversation to collaborators
on Oct 21, 2025
TypeScript Version: 3.6.2
Search Terms:
Repo
git clone https://github.com/Microsoft/typescript-template-language-service-decoratornpm installOpen
src/template-language-service-decorator.tsOn line 44, remove the any cast on the line:
Try compiling the project
Expected behavior:
This compiles with TS 3.4
Actual behavior:
Compile fails with TS 3.5+
The code likely needs to be rewritten here but I'm opening this issue to make sure the error is expected
Playground Link:
Related Issues: