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

5.1 regression: constraints of generic tuple types are sometimes order-sensitive #54495

Closed
alecgibson opened this issue Jun 2, 2023 · 13 comments Β· Fixed by #54536
Closed

5.1 regression: constraints of generic tuple types are sometimes order-sensitive #54495

alecgibson opened this issue Jun 2, 2023 · 13 comments Β· Fixed by #54536
Assignees
Labels
Fix Available A PR has been opened for this issue Needs More Info The issue still hasn't been fully clarified

Comments

@alecgibson
Copy link

Bug Report

πŸ”Ž Search Terms

  • 5.1
  • tuple
  • array
  • spread

Possibly related:

πŸ•— Version & Regression Information

  • This changed between versions v5.0.4 and v5.1.3

⏯ Playground Link

I was unable to reproduce: if you could please steer me in the right direction I'm happy to dig more, but I'm a bit stuck on how to debug this

πŸ’» Code

We have an issue using io-ts. If this is a bug with that library, I'll close this here, but I don't think it is.

The TypeScript compiler is complaining about a number of excerpts from the d.ts file, where the compiler doesn't seem to be making sense.

Here's an example error:

node_modules/io-ts/lib/index.d.ts:1151:24 - error TS2344: Type 'CS' does not satisfy the constraint '[Mixed, Mixed, Mixed[]]'.
  Type '[Mixed, Mixed, ...Mixed[]]' is not assignable to type '[Mixed, Mixed, Mixed[]]'.
    Target allows only 3 element(s) but source may have more.

1151 ) => TaggedUnionC<Tag, CS>

The code it's referring to is here:

export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Array<Mixed>]>
  extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}

export declare const taggedUnion: <Tag extends string, CS extends [Mixed, Mixed, ...Mixed[]]>(
  tag: Tag,
  codecs: CS,
  name?: string
) => TaggedUnionC<Tag, CS>

As you can see, the compiler seems to be collapsing the [Mixed, Mixed, ...Array<Mixed>] to [Mixed, Mixed, Mixed[]], which is incorrect. It then doesn't like CS extending [Mixed, Mixed, ...Mixed[]], which it considers incompatible with its incorrect collapsing.

Weirdly, if I tweak the d.ts file by hand, the error goes away:

- export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Array<Mixed>]>
+ export interface TaggedUnionC<Tag extends string, CS extends [Mixed, Mixed, ...Mixed[]]>

πŸ™ Actual behavior

Compilation errors

πŸ™‚ Expected behavior

Successful compilation

@RyanCavanaugh
Copy link
Member

I'm not able to reproduce this error. Can you post a concrete example?

@RyanCavanaugh RyanCavanaugh added the Needs More Info The issue still hasn't been fully clarified label Jun 2, 2023
@alecgibson
Copy link
Author

@RyanCavanaugh I tried to put together an MWE but I couldn't figure it out.

For some reason the error only happens with io-ts as a dependency of a dependency. The middle dependency compiles just fine with TS 5.1 and the issue only happens downstream with the transpiled JS and declaration files being used in 5.1.

Do you have any advice on how to get more information from TS, or a good guess at what might be the actual issue for me to narrow my search?

@Andarist
Copy link
Contributor

Andarist commented Jun 5, 2023

I'd recommend bisecting your situation by removing code from your dependencies, once you minimize this to a minimal repro you might want to just commit node_modules and share that as a repro case.

@alecgibson
Copy link
Author

Okay @RyanCavanaugh @Andarist I've got a minimal repro repo.

Turns out, nothing to do with our code, so either a TS bug, or a bug with another repo (still looks like TS to my uneducated eye, though).

The repro case β€” in the end β€” was laughably simple:

import 'mongodb';
import 'io-ts';

☝🏼 this fails to build with a bare-bones tsconfig.json on TypeScript v5.1.3 with the compilation error I mentioned above.

It builds fine on TypeScript v5.0.4.

@alecgibson
Copy link
Author

Please let me know if this is actually a bug with mongodb or io-ts, and I'll move there, but building a project that just depends on one of these libraries works just fine:

import 'mongodb';
- import 'io-ts';

or

- import 'mongodb';
import 'io-ts';

both work

@alecgibson
Copy link
Author

alecgibson commented Jun 5, 2023

Full error dump
❯ npm run build

> ts-spread-bug@1.0.0 build
> tsc --pretty

node_modules/io-ts/lib/index.d.ts:771:21 - error TS2344: Type 'CS' does not satisfy the constraint 'Any[]'.
  Type '[Mixed, Mixed, Mixed[]]' is not assignable to type 'Any[]'.
    Type 'Mixed | Mixed[]' is not assignable to type 'Any'.
      Type 'Mixed[]' is not assignable to type 'Type<any, any, any>'.

771   extends UnionType<CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}
                        ~~

node_modules/io-ts/lib/index.d.ts:771:32 - error TS2344: Type 'CS[number]' does not satisfy the constraint 'Any'.
  Type 'Mixed | Mixed[]' is not assignable to type 'Type<any, any, any>'.
    Type 'Mixed[]' is missing the following properties from type 'Type<any, any, any>': name, is, validate, encode, and 7 more.

771   extends UnionType<CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}
                                   ~~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:771:54 - error TS2344: Type 'CS[number]' does not satisfy the constraint 'Any'.

771   extends UnionType<CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}
                                                         ~~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:799:5 - error TS2344: Type 'CS' does not satisfy the constraint 'Any[]'.
  Type '[Mixed, Mixed, Mixed[]]' is not assignable to type 'Any[]'.
    Type 'Mixed | Mixed[]' is not assignable to type 'Any'.
      Type 'Mixed[]' is not assignable to type 'Type<any, any, any>'.

799     CS,
        ~~

node_modules/io-ts/lib/index.d.ts:807:48 - error TS2344: Type 'CS[2]' does not satisfy the constraint 'Any'.
  Type 'Mixed[]' is missing the following properties from type 'Type<any, any, any>': name, is, validate, encode, and 7 more.

807       ? TypeOf<CS[0]> & TypeOf<CS[1]> & TypeOf<CS[2]>
                                                   ~~~~~

node_modules/io-ts/lib/index.d.ts:824:54 - error TS2344: Type 'CS[2]' does not satisfy the constraint 'Any'.
  Type 'Mixed[]' is missing the following properties from type 'Type<any, any, any>': name, is, validate, encode, and 7 more.

824       ? OutputOf<CS[0]> & OutputOf<CS[1]> & OutputOf<CS[2]>
                                                         ~~~~~

node_modules/io-ts/lib/index.d.ts:846:58 - error TS2344: Type '[A, B, C, D, E]' does not satisfy the constraint '[Mixed, Mixed, Mixed[]]'.
  Source has 5 element(s) but target allows only 3.

846 >(codecs: [A, B, C, D, E], name?: string): IntersectionC<[A, B, C, D, E]>
                                                             ~~~~~~~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:850:18 - error TS2344: Type '[A, B, C, D]' does not satisfy the constraint '[Mixed, Mixed, Mixed[]]'.
  Source has 4 element(s) but target allows only 3.

850 ): IntersectionC<[A, B, C, D]>
                     ~~~~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:854:18 - error TS2344: Type '[A, B, C]' does not satisfy the constraint '[Mixed, Mixed, Mixed[]]'.
  Type at position 2 in source is not compatible with type at position 2 in target.
    Type 'C' is not assignable to type 'Mixed[]'.
      Type 'Type<any, any, unknown>' is missing the following properties from type 'Mixed[]': length, pop, push, concat, and 29 more.

854 ): IntersectionC<[A, B, C]>
                     ~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:1139:32 - error TS2344: Type 'CS' does not satisfy the constraint 'Mixed[]'.
  Type '[Mixed, Mixed, Mixed[]]' is not assignable to type 'Mixed[]'.
    Type 'Mixed | Mixed[]' is not assignable to type 'Mixed'.
      Type 'Mixed[]' is missing the following properties from type 'Type<any, any, unknown>': name, is, validate, encode, and 7 more.

1139   extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}
                                    ~~

node_modules/io-ts/lib/index.d.ts:1139:43 - error TS2344: Type 'CS[number]' does not satisfy the constraint 'Any'.
  Type 'Mixed | Mixed[]' is not assignable to type 'Type<any, any, any>'.
    Type 'Mixed[]' is not assignable to type 'Type<any, any, any>'.

1139   extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}
                                               ~~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:1139:65 - error TS2344: Type 'CS[number]' does not satisfy the constraint 'Any'.

1139   extends TaggedUnionType<Tag, CS, TypeOf<CS[number]>, OutputOf<CS[number]>, unknown> {}
                                                                     ~~~~~~~~~~

node_modules/io-ts/lib/index.d.ts:1151:24 - error TS2344: Type 'CS' does not satisfy the constraint '[Mixed, Mixed, Mixed[]]'.
  Type '[Mixed, Mixed, ...Mixed[]]' is not assignable to type '[Mixed, Mixed, Mixed[]]'.
    Target allows only 3 element(s) but source may have more.

1151 ) => TaggedUnionC<Tag, CS>
                            ~~


Found 13 errors in the same file, starting at: node_modules/io-ts/lib/index.d.ts:771

@Andarist
Copy link
Contributor

Andarist commented Jun 5, 2023

This can be bisected to this PR #53672 , cc @ahejlsberg

That being said, this isn't quite a minimal repro case πŸ˜‰ mongodb and io-ts have a lot of types and it might take a while for somebody to actually reduce this.

Note that reordering those 2 imports also fixes the issue so it's likely a caching bug in the compiler. Things are cached for performance reasons and unfortunately, sometimes issues like this pop up and at times it's hard to fix them. Ideally, the order of declarations shouldn't matter but in practice, it sometimes might.

@alecgibson
Copy link
Author

Sorry I guess I meant minimal in terms of code I actually wrote πŸ˜…

Unfortunately I'm not sure I personally have time to unpick the internal type dependencies of these packages 😬

@Andarist I'm not really sure I understand what the actual issue is: do you have a suggestion for a more accurate issue title for this?

@Andarist
Copy link
Contributor

Andarist commented Jun 5, 2023

Maybe something like: "5.1 regression: constraints of generic tuple types are sometimes order-sensitive"

@alecgibson alecgibson changed the title 5.1 Regression: Spread Array types inside tuple incorrectly collapsed 5.1 regression: constraints of generic tuple types are sometimes order-sensitive Jun 5, 2023
@alecgibson
Copy link
Author

Okay I spotted something as I was skimming the MongoDB type declarations, and it looks like if you comment out this suspicious-looking type (and things that depend on it), everything compiles just fine.

I've pushed the result to the above repo as a new branch: commented-deps

Is this a TypeScript bug or a MongoDB bug?

@typescript-bot typescript-bot added the Fix Available A PR has been opened for this issue label Jun 5, 2023
@ahejlsberg ahejlsberg self-assigned this Jun 5, 2023
@ahejlsberg ahejlsberg added this to the TypeScript 5.1.4 milestone Jun 5, 2023
@alecgibson
Copy link
Author

@Andarist @ahejlsberg this is still broken in 5.1.5. Should it be fixed?

@Andarist
Copy link
Contributor

It seems that the fix was supposed to be cherry-picked into 5.1 but the automated job failed, see the comment here. cc @DanielRosenwasser @jakebailey

@jakebailey
Copy link
Member

I just sent #54814 to cherry-pick it by hand. Unfortunate; I totally read that notification in my email but I figured it was already handled...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants