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

Do not measure variance for a conditional type extendsType #31277

Conversation

jack-williams
Copy link
Collaborator

Attempts to fix #31251

@falsandtru
Copy link
Contributor

ping @weswigham

@jack-williams
Copy link
Collaborator Author

This PR does not address variance issues stemming from check types (see #31295 as an example). I wonder if it is best to try and fix them together?

@falsandtru
Copy link
Contributor

ping @ahejlsberg @weswigham

1 similar comment
@falsandtru
Copy link
Contributor

ping @ahejlsberg @weswigham

@weswigham
Copy link
Member

@jack-williams can you sync this? We'd want to test this across DT with perf in mind before merging it, which is our primary concern with using Unmeasurable and Unreliable more.

@jack-williams
Copy link
Collaborator Author

@weswigham done!

@weswigham
Copy link
Member

@typescript-bot run dt
@typescript-bot test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 12, 2019

Heya @weswigham, I've started to run the parallelized Definitely Typed test suite on this PR at 70336e6. You can monitor the build here. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 12, 2019

Heya @weswigham, I've started to run the extended test suite on this PR at 70336e6. You can monitor the build here. It should now contribute to this PR's status checks.

@falsandtru
Copy link
Contributor

@jack-williams Can you resolve the errors?

@weswigham Can you run @typescript-bot pack this?

@weswigham
Copy link
Member

Sure - @typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 16, 2019

Heya @weswigham, I've started to run the tarball bundle task on this PR at 70336e6. You can monitor the build here. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

Hey @weswigham, I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
    "devDependencies": {
        "typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/33400/artifacts?artifactName=tgz&fileId=B10B0A88C3D1C8DCA0C6AA5DDED4DD385013554114808F4B3A5FBB56317A12D102&fileName=/typescript-3.6.0-insiders.20190616.tgz"
    }
}

and then running npm install.

@falsandtru
Copy link
Contributor

Thanks.

@jack-williams Comparison targets are still reversed:

Type 'typeof Book' does not satisfy the constraint 'typeof AnyModel'.
  Types of property 'reducer' are incompatible.
    Type '(action: RootAction, Book: ModelType<Book>) => void' is not assignable to type '(action: any, modelType: ModelType<any>, session: Pick<Pick<Session<any>, never> & Pick<{ [x: string]: ModelType<any>; }, never> & Pick<{ [x: string]: ModelType<any>; }, string | number | symbol>, string | ... 1 more ... | symbol>) => void'.
      Types of parameters 'Book' and 'modelType' are incompatible.
        Type 'ModelType<any>' is not assignable to type 'ModelType<Book>'.
          ...

It should be

-        Type 'ModelType<any>' is not assignable to type 'ModelType<Book>'.
+        Type 'ModelType<Book>' is not assignable to type 'ModelType<any>'.

@jack-williams
Copy link
Collaborator Author

@falsandtru can you give me the full example? This might be an issue with the check type, not the extends type.

@jack-williams
Copy link
Collaborator Author

It should be
Type 'ModelType<Book>' is not assignable to type 'ModelType<any>'.

Should it? The type appears in an argument position so I would expect them to be flipped when running strictFunctionTypes

I don't really have time to debug DT right now, but I wouldn't be surprised if this was correctly an error, something along the line of:

interface Foo<T,U> {
	x: T extends U ? number : string;
}
declare const a: Foo<any, boolean>;
let b: Foo<boolean, boolean> = a; // no error, but it should be

@falsandtru
Copy link
Contributor

I referred to that line to explain the comparison order. Of course it should be no error if any type makes no errors.

@jack-williams
Copy link
Collaborator Author

@typescript-bot run dt because the old builds logs were cleared up.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Aug 18, 2019

Heya @jack-williams, I've started to run the parallelized Definitely Typed test suite on this PR at 52c7dff. You can monitor the build here. It should now contribute to this PR's status checks.

@jack-williams
Copy link
Collaborator Author

I need to look into some of the changes to see whether they are reasonable, and more likely, what is the corresponding fix. Most of them seem to be cases where something is constrained with a type Interface<any> that previously passed on variance checks, but no longer does.

@weswigham
Copy link
Member

I believe that. What we've been trying to do as of late is to fix the breaks on DT (via PRs to DT) such that we can get a clean run on the PR. It normally works out pretty well in cases like these where you can say "this was a possible way the old types could have been misused, TS with this new PR catches this, and this change preemptively fixes the package so it won't be broken by the next TS release".

if (isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
(isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) || isRelatedTo((<ConditionalType>target).checkType, (<ConditionalType>source).checkType))) {
const u1 = instantiateType((<ConditionalType>source).extendsType, reportUnmeasurableMarkers);
const u2 = instantiateType((<ConditionalType>target).extendsType, reportUnmeasurableMarkers);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source and target are identical sans type parameter instantiations during variance checking, so I've been wondering if we can get away with only instantiating one of the source or target.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that feels like it should work. At least, I don't see how replacing a type parameter with a sub/super type of itself could affect whether it gets instantiated.

@falsandtru
Copy link
Contributor

Can you merge?

@falsandtru
Copy link
Contributor

I found a regression on https://github.com/falsandtru/spica.

src/list.ts(46,13): Error TS2352: Conversion of type '(as extends [unknown, unknown, ...unknown[]] ? as : never)["length"] extends 1 ? Nil : Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' to type 'Cons<Split<as>[1]>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type 'Nil | Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<Split<as>[1]>'.
    Type 'Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<Split<as>[1]>'.
      Types of property 'tail' are incompatible.
        Type 'Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]["length"] extends 1 ? Nil : Cons<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>' is not comparable to type 'Split<as>[1]["length"] extends 1 ? Nil : Cons<Split<Split<as>[1]>[1]>'.
          Type 'Cons<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>' is not comparable to type 'Cons<Split<Split<as>[1]>[1]>'.
            Types of property 'tail' are incompatible.
              Type 'Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>' is not comparable to type 'Split<Split<as>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<as>[1]>[1]>[1]>'.
                Type 'Cons<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>' is not comparable to type 'Cons<Split<Split<Split<as>[1]>[1]>[1]>'.
                  Types of property 'tail' are incompatible.
                    Type 'Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>[1]>' is not comparable to type 'Split<Split<Split<as>[1]>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<Split<as>[1]>[1]>[1]>[1]>'.
                      Type 'Cons<Split<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>[1]>' is not comparable to type 'Cons<Split<Split<Split<Split<as>[1]>[1]>[1]>[1]>'.      
                        The types returned by 'reverse()' are incompatible between these types.
                          Type 'Reverse<Split<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>[1]>' is not comparable to type 'Reverse<Split<Split<Split<Split<as>[1]>[1]>[1]>[1]>'.

@falsandtru
Copy link
Contributor

The error come from this.tail as Cons<Split<as>[1]> but the error message of this.tail as Cons<Split<AtLeast<2, unknown>>[1]> would be more readable.

Conversion of type '(as extends [unknown, unknown, ...unknown[]] ? as : never)["length"] extends 1 ? Nil : Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' to type 'Cons<[unknown, ...unknown[]]>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type 'Nil | Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<[unknown, ...unknown[]]>'.
    Type 'Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<[unknown, ...unknown[]]>'.
      Types of property 'CONS' are incompatible.
        Type 'Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]' is not comparable to type '[unknown, ...unknown[]]'.
          Type 'Split<as>[1]' is not comparable to type '[unknown, ...unknown[]]'.
            Property '0' is missing in type 'unknown[]' but required in type '[unknown, ...unknown[]]'.ts(2352)

At the following place,

          Type 'Split<as>[1]' is not comparable to type '[unknown, ...unknown[]]'.
            Property '0' is missing in type 'unknown[]' but required in type '[unknown, ...unknown[]]'.ts(2352)

Split<as>[1] must be [unknown, ...unknown[]] but looks like the compiler assumes unknown[].

@DanielRosenwasser
Copy link
Member

@jack-williams pointed out this is still open on #36138. Did you get the chance to take a look at this @ahejlsberg?

@falsandtru
Copy link
Contributor

#31277 (comment) is missing. Can you pack again?

@jack-williams
Copy link
Collaborator Author

@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jan 27, 2020

Heya @jack-williams, I've started to run the tarball bundle task on this PR at aa4138d. You can monitor the build here. It should now contribute to this PR's status checks.

@falsandtru
Copy link
Contributor

Hm, the task has failed.

@jack-williams
Copy link
Collaborator Author

@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jan 27, 2020

Heya @jack-williams, I've started to run the tarball bundle task on this PR at 81943cc. You can monitor the build here. It should now contribute to this PR's status checks.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jan 27, 2020

Hey @jack-williams, I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
    "devDependencies": {
        "typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/61972/artifacts?artifactName=tgz&fileId=053FA4BCC915C26D801DF489ED85164BFCAFFD0BBA6F61B75D49F244F4916BDF02&fileName=/typescript-3.8.0-insiders.20200127.tgz"
    }
}

and then running npm install.


There is also a playground for this build.

@falsandtru
Copy link
Contributor

Thanks. I cleaned the related type functions by removing unnecessary constraints but that made no effect. The current errors are as follows.

spica/src/list.ts(46,13): Error TS2352: Conversion of type '(as extends [unknown, unknown, ...unknown[]] ? as : never)["length"] extends 1 ? Nil : Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' to type 'Cons<Split<as>[1]>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type 'Nil | Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<Split<as>[1]>'.
    Type 'Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<Split<as>[1]>'.
      Types of property 'tail' are incompatible.
        Type 'Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]["length"] extends 1 ? Nil : Cons<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>' is not comparable to type 'Split<as>[1]["length"] extends 1 ? Nil : Cons<Split<Split<as>[1]>[1]>'.
          Type 'Cons<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>' is not comparable to type 'Cons<Split<Split<as>[1]>[1]>'.
            Types of property 'tail' are incompatible.
              Type 'Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>' is not comparable to type 'Split<Split<as>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<as>[1]>[1]>[1]>'.
                Type 'Cons<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>' is not comparable to type 'Cons<Split<Split<Split<as>[1]>[1]>[1]>'.
                  Types of property 'tail' are incompatible.
                    Type 'Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>[1]>' is not comparable to type 'Split<Split<Split<as>[1]>[1]>[1]["length"] extends 1 ? Nil : Cons<Split<Split<Split<Split<as>[1]>[1]>[1]>[1]>'. 
                      Type 'Cons<Split<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>[1]>' is not comparable to type 'Cons<Split<Split<Split<Split<as>[1]>[1]>[1]>[1]>'.
                        The types returned by 'reverse()' are incompatible between these types.
                          Type 'Reverse<Split<Split<Split<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>[1]>[1]>[1]>' is not comparable to type 'Reverse<Split<Split<Split<Split<as>[1]>[1]>[1]>[1]>'.
spica/src/list.ts(46,13): Error TS2352: Conversion of type '(as extends [unknown, unknown, ...unknown[]] ? as : never)["length"] extends 1 ? Nil : Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' to type 'Cons<[unknown, ...unknown[]]>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type 'Nil | Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<[unknown, ...unknown[]]>'.
    Type 'Cons<Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]>' is not comparable to type 'Cons<[unknown, ...unknown[]]>'.
      Types of property 'CONS' are incompatible.
        Type 'Split<as extends [unknown, unknown, ...unknown[]] ? as : never>[1]' is not comparable to type '[unknown, ...unknown[]]'.
          Type 'Split<as>[1]' is not comparable to type '[unknown, ...unknown[]]'.
            Property '0' is missing in type 'unknown[]' but required in type '[unknown, ...unknown[]]'.

@sandersn sandersn added the For Milestone Bug PRs that fix a bug with a specific milestone label Feb 1, 2020
@sandersn
Copy link
Member

sandersn commented Mar 3, 2020

It sounds like this PR is currently blocked on #30639. Is that a correct reading of the comment history @jack-williams?

@jack-williams
Copy link
Collaborator Author

@sandersn Blocked may be too strong, but I think it makes sense to merge #30639 first, if possible. This PR makes the compiler check more conditional types structurally, so having more relation rules seems good.

I believe #30639 would change some of the breaks introduced by this PR, but I haven't checked DT in a while.

@weswigham
Copy link
Member

@jack-williams #30639 got merged this release! Do we need to refresh/reevaluate breaks? I imagine so since the last update in here was march of last year.

@jack-williams
Copy link
Collaborator Author

@weswigham I've started trying to revive this. There is one new regression in the compiler tests which I have not been able to figure out yet, but I have been able to reduce to a small example:

type EqualsTest<T> = <A>() => A extends T ? 1 : 0;
type EqualsTest1<T> = <A>() => A extends T ? 1 : 0;

const x: EqualsTest<number> = undefined as any as EqualsTest<string>; // was error, now no error
const y: EqualsTest<number> = undefined as any as EqualsTest1<string>; // error;

Both used to fail, now only y does.

@weswigham
Copy link
Member

Information loss during generic signature relating due to local type parameters erasure is I think likely at fault there, like I (tried to) explain in #43867.

@weswigham
Copy link
Member

weswigham commented Apr 29, 2021

Specifically the self-assignment case lacks the error because we have a "fast path" in signature comparison (in signaturesRelatedTo) for when we're relating two signatures from the same type in which both copies of the signature have their type parameters erased to any, which in turn causes us to fully evaluate the conditional (to a union of both branches) when we do the structural comparison, which is why we fail to issue an error. Type erasure has another outstanding issue - #41067 - which I don't think would help here, since the wildcard is just a special any, so the conditionals would still incorrectly execute and eliminate the extends clause, but I think points to a possible solution - we need the "erased" type parameter to be assignable like an any, but still prevent execution of conditionals, and thus look like a generic. That's neither any, nor the wildcardType right now, but I don't think it'd be too bad to clone one of the two and consider it "instantiable" in the context of constructing a conditional (and thus prevent its execution).

I have just put together a composition of this change, the change in #41067, and what I just explained, which seems to neatly tie all this together and get our conditionals-in-generic-signatures relationships to where I think it should be. I've put up #43887 with that.

@jack-williams
Copy link
Collaborator Author

Thanks @weswigham, your description on the first thread was clear, I just didn't read it in enough detail. The any from the generic erasure causing problems makes sense.

I will close this up in favor of your new PR. Without your change this PR break Equal from ts-toolbelt, and likely other type heavy packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Milestone Bug PRs that fix a bug with a specific milestone
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Comparison targets are reversed (regression)
7 participants