Skip to content

Regression 5.4: the new conditional type constraint is not working with a type parameter representing union typeΒ #57864

Closed as not planned
@Alexsey

Description

@Alexsey

πŸ”Ž Search Terms

regression, type parameter, 5.4

πŸ•— Version & Regression Information

  • This is a crash
  • This changed between versions 5.3.3 and 5.4.2

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.2#code/C4TwDgpgBAggznAlgcwHYCUJwK4BtgA8MATsVBAB7ASoAmcUA9gEYBWEAxsANoC6AfFAC8sUgCgxAeklRuqPLgA0UeQFtmEYsux0IAM0SoItZXGDFDyXsMFzs6zafOXeY0JCgAxRPk1FSygAqjADyqojAgiIkZJTUdAzchnqaUAASEACGJlAAdPnJqYGZPq5QUAD86Vm05FQ09FDBYRFi5eVV3r7EBMU+QaHhkW3tAFyyGdnK+bld1D19Sk2DEfxlUON8ANwS7tAA6ozEANZwAAoWRwCsACwEAMp18Y0s7FxQAD4qClGwCCgYLB4QhzPz3ZTyXC4fj8XbgA5HU7CP5INCYHD4AignqvTjAT7fKEQn78IA

πŸ’» Code

This is the simplified code

type AssignResult<Arr extends object[]> = Arr

// [null, number, undefined, string] => [number, string]
type Filter<Arr, ToOmit> = Arr extends [infer Head, ...infer Tail]
  ? Head extends ToOmit
    ? Filter<Tail, ToOmit>
    : [Head, ...Filter<Tail, ToOmit>]
  : [];

type WorksPrior54<S extends object | null> = AssignResult<Filter<S, null>>

type Works = AssignResult<Filter<object | null, null>>
This is the full code (error message is slightly different, but probably they are the same):
type AssignResult<Arr extends object[]> = Arr extends [...infer Rest extends object[], infer Last]
  ? {
    [K in keyof Last | keyof AssignResult<Rest>]: K extends keyof Last
      ? Last[K]
      : K extends keyof AssignResult<Rest>
        ? AssignResult<Rest>[K]
        : never;
  }
  : object;

type Filter<Arr, ToOmit> = Arr extends [infer Head, ...infer Tail]
  ? Head extends ToOmit
    ? Filter<Tail, ToOmit>
    : [Head, ...Filter<Tail, ToOmit>]
  : [];

declare function assignByDescriptors<
  Target extends object,
  // replace the two lines below to make it work with the this line
  // Sources extends (object | null | undefined)[],
  Source extends object | null | undefined,
  Sources extends Source[],
  Result extends AssignResult<[Target, ...Filter<Sources, null | undefined>]> = AssignResult<[Target, ...Filter<Sources, null | undefined>]>
>(target: Target, ...sources: Sources): Result

πŸ™ Actual behavior

I would expect to have no error for 5.4, the same as there was no error before it. Especially considering that there were not breaking changes in 5.4 announcement.

As for the simplified code, there should be no difference between how WorksPrior54 and Works.

As for the full version of the code, there should be no difference if part of Sources type parameter is extracted into an intermediate Source type parameter, or not

πŸ™‚ Expected behavior

Error (in the simplified version):

TS2344: Type Filter<S, null> does not satisfy the constraint object[]
Type [] | [unknown] is not assignable to type object[]
Type [unknown] is not assignable to type object[]

Error (in the full version):

TS2344: Type
[Target, ...Filter<Sources, null | undefined>]
does not satisfy the constraint object[]
Type
Target | Filter<Sources, null | undefined>[number]
is not assignable to type object
Type Filter<Sources, null | undefined>[number] is not assignable to type object
Type
(Source extends null | undefined ? [] : [Source])[number] | (Source extends null | undefined ? [] : [Source])[number]
is not assignable to type object
Type
(Source extends null | undefined ? [] : [Source])[number]
is not assignable to type object

Additional information about the issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions