Skip to content

Large enum causes React hook deps error TS2590 Expression produces a union type that is too complex to represent #41615

Description

@brieb

We use React hooks with TypeScript and ran into an issue where we were passing a large enum into the dependency array of the hook function, resulting in TS2590 Expression produces a union type that is too complex to represent

This is an example type signature of a hook
function React.useEffect(effect: React.EffectCallback, deps?: React.DependencyList | undefined): void

Even though the deps type is React.DependencyList which is type DependencyList = ReadonlyArray<any>; it appears to be attempting a union deps: (MyEnum1 | MyEnum2 | MyInterface)[] even though the type is ultimately discarded.

This gives the same error const deps: any[] = [MyEnum1.Key0, MyEnum2.Key0, obj];

We could do [MyEnum1.Key0 as any, MyEnum2.Key0 as any, obj] but that is not ideal and also breaks the rules of hooks eslint rule.

Another workaround we came up with was [MyEnum1.Key0, MyEnum2.Key0, obj] as const to avoid the unioning (though this fails the hooks eslint rule which sounds like a separate issue).

Thanks in advance for your help.

TypeScript Version: 4.0.5

Search Terms: react hooks deps, dependency array, union type that is too complex

Code

https://gist.github.com/brieb/ef53a9e48e8a5dec6cfa7d2cfda22623

Expected behavior:

No compiler error

Actual behavior:

TS2590 error: Expression produces a union type that is too complex to represent.

Playground Link:

Link

Related Issues:
#33130

Activity

  1. DanielRosenwasser commented on Dec 3, 2020

    @DanielRosenwasser
    Member

    This gives the same error const deps: any[] = [MyEnum1.Key0, MyEnum2.Key0, obj];

    It really sounds like the hooks thing is a separate issue and it comes down to 2 large enums and an object type...

  2. DanielRosenwasser commented on Dec 3, 2020

    @DanielRosenwasser
    Member

    So one thing that I know will help is combining your enums into one.

    Otherwise, we don't currently have a good heuristic to avoid triggering the subtype reduction check. I did try the following really naive change to avoid flattening out the entire enum:

             function addTypeToUnion(typeSet: Type[], includes: TypeFlags, type: Type) {
                 const flags = type.flags;
    -            if (flags & TypeFlags.Union) {
    +            if (flags & TypeFlags.Union && !(flags & TypeFlags.EnumLike)) {
                     return addTypesToUnion(typeSet, includes, (<UnionType>type).types);

    but for some reason I had issues running locally in parallel.

    Maybe Anders Hejlsberg (@ahejlsberg) or Wesley Wigham (@weswigham) have some ideas here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions