-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Fixed the issue with some longer variadic tuples with any
rest being incorrectly assignable to shorter variadic tuples
#50218
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5691,9 +5691,12 @@ namespace ts { | |
|
||
export interface TupleType extends GenericType { | ||
elementFlags: readonly ElementFlags[]; | ||
minLength: number; // Number of required or variadic elements | ||
fixedLength: number; // Number of initial required or optional elements | ||
hasRestElement: boolean; // True if tuple has any rest or variadic elements | ||
/** Number of required or variadic elements */ | ||
minLength: number; | ||
/** Number of initial required or optional elements */ | ||
fixedLength: number; | ||
/** True if tuple has any rest or variadic elements */ | ||
hasRestElement: boolean; | ||
Comment on lines
+5694
to
+5699
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By moving those to JSDocs we improve slightly the IDE experience as this information gets displayed in the tooltips when hovering over those properties |
||
combinedFlags: ElementFlags; | ||
readonly: boolean; | ||
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,12 +18,10 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(33,31): error TS2344: | |
Type 'string' is not assignable to type 'number'. | ||
tests/cases/conformance/types/tuple/restTupleElements1.ts(34,31): error TS2344: Type '[number, number, string]' does not satisfy the constraint '[number, ...number[]]'. | ||
Type at positions 1 through 2 in source is not compatible with type at position 1 in target. | ||
Type 'string | number' is not assignable to type 'number'. | ||
Type 'string' is not assignable to type 'number'. | ||
Type 'string' is not assignable to type 'number'. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A change like this is correct with the new logic. As mentioned in the other comment - I no longer create unions from "tuple slices". That's why the reported source is just a "single" type here and not a union. I think that perhaps this error could be somehow improved/rephrased cause it mentions a position span in the source where in fact the type mismatch happens only on a given position (or only on some positions of this span). The mentioned span covers all of the positions in the source that must match a single position of the rest in the target. Note though that reporting a single type here is not completely new, this could always happen in cases like this: declare let tt3: [number, string, ...string[]];
let tt4: [number, ...number[]] = tt3;
// Type '[number, string, ...string[]]' is not assignable to type '[number, ...number[]]'.
// Type at positions 1 through 2 in source is not compatible with type at position 1 in target.
// Type 'string' is not assignable to type 'number'.(2322) I think there is a potential of just dropping this specific error: I've decided not to introduce this change here to limit the scope of the PR and to minimize the initial diff to make it easier to review it. |
||
tests/cases/conformance/types/tuple/restTupleElements1.ts(35,31): error TS2344: Type '[number, number, number, string]' does not satisfy the constraint '[number, ...number[]]'. | ||
Type at positions 1 through 3 in source is not compatible with type at position 1 in target. | ||
Type 'string | number' is not assignable to type 'number'. | ||
Type 'string' is not assignable to type 'number'. | ||
Type 'string' is not assignable to type 'number'. | ||
tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: Argument of type '[]' is not assignable to parameter of type '[unknown, ...unknown[]]'. | ||
Source has 0 element(s) but target requires 1. | ||
|
||
|
@@ -94,14 +92,12 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: A | |
~~~~~~~~~~~~~~~~~~~~~~~~ | ||
!!! error TS2344: Type '[number, number, string]' does not satisfy the constraint '[number, ...number[]]'. | ||
!!! error TS2344: Type at positions 1 through 2 in source is not compatible with type at position 1 in target. | ||
!!! error TS2344: Type 'string | number' is not assignable to type 'number'. | ||
!!! error TS2344: Type 'string' is not assignable to type 'number'. | ||
!!! error TS2344: Type 'string' is not assignable to type 'number'. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm ok with that change. The message could be better, because what ultimately fails is the type at position 2 in source, so we could be more specific. But considering we had the same problem before this PR, it seems out of scope for this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could improve on this error message here or in a followup PR - I would need a confirmation on how this should be reported though. I guess that in this case, I should drop the "positions X through Y" bit and just report this error for the fixed~ position. IIRC this would mean that |
||
assign<[number, ...number[]], [number, number, number, string]>(); // Error | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
!!! error TS2344: Type '[number, number, number, string]' does not satisfy the constraint '[number, ...number[]]'. | ||
!!! error TS2344: Type at positions 1 through 3 in source is not compatible with type at position 1 in target. | ||
!!! error TS2344: Type 'string | number' is not assignable to type 'number'. | ||
!!! error TS2344: Type 'string' is not assignable to type 'number'. | ||
!!! error TS2344: Type 'string' is not assignable to type 'number'. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, given what we've had before, I think this is good. It actually might be more clear than the previous message, because before we had There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I also found the union type being reported here kinda unintuitive. |
||
|
||
type T20 = [number, string, ...boolean[]]; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The core of the fix is in the iteration "style". Previously we were iterating over
targetArity
and "slicing" a source in the position of the target rest element.When we consider the added test case:
It means that for the target's
...number[]
we were creating a slice from those elements:string, ...any[]
. This, in turn, was indexed~/unionized and thus becamestring | any
which is just an equivalent ofany
. And that was used as a source type for the target, introducing a bug.I've flipped this and now this loop iterates over
sourceArity
. This ensures that a specific position in the source is assignable, in "isolation", to the respective target position.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From testing this code with some examples and carefully reading through it, I think it's at least as correct as before (and more, now that it fixes the bug). I still need to review the error messages though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for the review! I know that there are some changes in the error messages and stuff - just want to let you know that I would happily make any required adjustments to this PR, but when it comes to those error messages I need to know what would be the expected results. IIRC the current messages are not incorrect - but perhaps you'd like to have them improved somehow.