Skip to content
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

Incorrect Merge with optional any fields #579

Closed
center-777 opened this issue Mar 25, 2023 · 1 comment · Fixed by #583
Closed

Incorrect Merge with optional any fields #579

center-777 opened this issue Mar 25, 2023 · 1 comment · Fixed by #583

Comments

@center-777
Copy link

Hi!

First of all, sorry for my english 🤷‍♂️

I found a problem with incorrect merging of types with optional any fields.
Tested on version 3.7.0.

Current Merge type is:

type Merge<Destination, Source> = EnforceOptional<
    SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
    & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;

and next code gives us type with all required fields:

type DestinationWithOptionalAnyKeys = {
	a?: any;
	c: string;
	d?: any;
	e: number;
};
type SourceWithOptionalAnyKeys = {
	b?: any;
	c?: any;
	d: number;
};
type DestinationSourceWithOptionalAnyKeys = Merge<DestinationWithOptionalAnyKeys, SourceWithOptionalAnyKeys>;

declare const destinationSourceWithOptionalAnyKeys: DestinationSourceWithOptionalAnyKeys;
// destinationSourceWithOptionalAnyKeys => {
//      a: any,
//      b: any,
//      c: any,
//      d: number,
//      e: number
//  }

The problem is that the Merge try set optional fields with EnforceOptional, which makes optional only * | undefined fields.
But fields with any other types will stay required.

So, if we rewrite Merge type as:

type Merge<Destination, Source> =
    EnforceOptional<
        // At this point we set all fields except required as optional
        SetOptional<
            SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
            & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>,
            Exclude<
                OptionalKeysOf<PickIndexSignature<Destination> & OmitIndexSignature<Destination>>
                | OptionalKeysOf<PickIndexSignature<Source> & OmitIndexSignature<Source>>,
                RequiredKeysOf<PickIndexSignature<Source> & OmitIndexSignature<Source>>>>>;

we will get the correct result:

// destinationSourceWithOptionalAnyKeys => {
//     d: number,
//     e: number,
//     a?: any,
//     b?: any,
//     c?: any
// }

It solves a problem with optional any type fields, but gives "Type instantiation is excessively deep and possibly infinite" error at MergeDeep type in tests:

Снимок экрана 2023-03-26 в 01 07 55

Снимок экрана 2023-03-26 в 01 09 59

Variables fooBarTupleSpread and fooBarTupleReplace casts to any type because of this error.

Does anyone have any ideas, how can i fix it?

@center-777 center-777 changed the title Incorrect Merge with optional any field Incorrect Merge with optional any fields Mar 25, 2023
@david-crespo
Copy link

david-crespo commented Mar 27, 2023

I think this is a duplicate of #506, or at least related

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants