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

Fix tuple name homogeneity check #40118

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/compiler/checker.ts
Expand Up @@ -31080,13 +31080,10 @@ namespace ts {
function checkTupleType(node: TupleTypeNode) {
const elementTypes = node.elements;
let seenOptionalElement = false;
let seenNamedElement = false;
const hasNamedElement = some(elementTypes, isNamedTupleMember);
for (let i = 0; i < elementTypes.length; i++) {
const e = elementTypes[i];
if (e.kind === SyntaxKind.NamedTupleMember) {
seenNamedElement = true;
}
else if (seenNamedElement) {
if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
break;
}
Expand Down
34 changes: 23 additions & 11 deletions tests/baselines/reference/namedTupleMembersErrors.errors.txt
@@ -1,28 +1,40 @@
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(1,41): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(3,32): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(5,32): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(7,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(9,46): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(11,49): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(11,52): error TS8020: JSDoc types can only be used inside documentation comments.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(13,39): error TS5085: A tuple member cannot be both optional and rest.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(15,44): error TS2574: A rest element type must be an array type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(17,13): error TS2456: Type alias 'RecusiveRestUnlabeled' circularly references itself.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(18,13): error TS2456: Type alias 'RecusiveRest' circularly references itself.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(2,25): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(4,32): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(5,22): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(7,32): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(8,22): error TS5084: Tuple members must all have names or all not have names.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(10,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(12,46): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(14,49): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(14,52): error TS8020: JSDoc types can only be used inside documentation comments.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(16,39): error TS5085: A tuple member cannot be both optional and rest.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(18,44): error TS2574: A rest element type must be an array type.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(20,13): error TS2456: Type alias 'RecusiveRestUnlabeled' circularly references itself.
tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(21,13): error TS2456: Type alias 'RecusiveRest' circularly references itself.


==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (11 errors) ====
==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (14 errors) ====
export type Segment1 = [length: number, number]; // partially named, disallowed
~~~~~~
!!! error TS5084: Tuple members must all have names or all not have names.
export type Segment2 = [number, size: number]; // partially named, disallowed
~~~~~~
!!! error TS5084: Tuple members must all have names or all not have names.

export type List = [item: any, ...any]; // partially named, disallowed
~~~~~~
!!! error TS5084: Tuple members must all have names or all not have names.
export type List2 = [any, ...remainder: any]; // partially named, disallowed
~~~
!!! error TS5084: Tuple members must all have names or all not have names.

export type Pair = [item: any, any?]; // partially named, disallowed
~~~~
!!! error TS5084: Tuple members must all have names or all not have names.
export type Pair2 = [any, last?: any]; // partially named, disallowed
~~~
!!! error TS5084: Tuple members must all have names or all not have names.

export type Opt = [element: string?]; // question mark on element disallowed
~~~~~~~
Expand Down
6 changes: 6 additions & 0 deletions tests/baselines/reference/namedTupleMembersErrors.js
@@ -1,9 +1,12 @@
//// [namedTupleMembersErrors.ts]
export type Segment1 = [length: number, number]; // partially named, disallowed
export type Segment2 = [number, size: number]; // partially named, disallowed

export type List = [item: any, ...any]; // partially named, disallowed
export type List2 = [any, ...remainder: any]; // partially named, disallowed

export type Pair = [item: any, any?]; // partially named, disallowed
export type Pair2 = [any, last?: any]; // partially named, disallowed

export type Opt = [element: string?]; // question mark on element disallowed

Expand All @@ -26,8 +29,11 @@ exports.__esModule = true;

//// [namedTupleMembersErrors.d.ts]
export declare type Segment1 = [length: number, number];
export declare type Segment2 = [number, size: number];
export declare type List = [item: any, ...any];
export declare type List2 = [any, ...remainder: any];
export declare type Pair = [item: any, any?];
export declare type Pair2 = [any, last?: any];
export declare type Opt = [element: string?];
export declare type Trailing = [first: string, rest: ...string[]];
export declare type OptTrailing = [first: string, rest: ...?string[]];
Expand Down
31 changes: 20 additions & 11 deletions tests/baselines/reference/namedTupleMembersErrors.symbols
Expand Up @@ -2,32 +2,41 @@
export type Segment1 = [length: number, number]; // partially named, disallowed
>Segment1 : Symbol(Segment1, Decl(namedTupleMembersErrors.ts, 0, 0))

export type Segment2 = [number, size: number]; // partially named, disallowed
>Segment2 : Symbol(Segment2, Decl(namedTupleMembersErrors.ts, 0, 48))

export type List = [item: any, ...any]; // partially named, disallowed
>List : Symbol(List, Decl(namedTupleMembersErrors.ts, 0, 48))
>List : Symbol(List, Decl(namedTupleMembersErrors.ts, 1, 46))

export type List2 = [any, ...remainder: any]; // partially named, disallowed
>List2 : Symbol(List2, Decl(namedTupleMembersErrors.ts, 3, 39))

export type Pair = [item: any, any?]; // partially named, disallowed
>Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 2, 39))
>Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 4, 45))

export type Pair2 = [any, last?: any]; // partially named, disallowed
>Pair2 : Symbol(Pair2, Decl(namedTupleMembersErrors.ts, 6, 37))

export type Opt = [element: string?]; // question mark on element disallowed
>Opt : Symbol(Opt, Decl(namedTupleMembersErrors.ts, 4, 37))
>Opt : Symbol(Opt, Decl(namedTupleMembersErrors.ts, 7, 38))

export type Trailing = [first: string, rest: ...string[]]; // dots on element disallowed
>Trailing : Symbol(Trailing, Decl(namedTupleMembersErrors.ts, 6, 37))
>Trailing : Symbol(Trailing, Decl(namedTupleMembersErrors.ts, 9, 37))

export type OptTrailing = [first: string, rest: ...string[]?]; // dots+question on element disallowed
>OptTrailing : Symbol(OptTrailing, Decl(namedTupleMembersErrors.ts, 8, 58))
>OptTrailing : Symbol(OptTrailing, Decl(namedTupleMembersErrors.ts, 11, 58))

export type OptRest = [first: string, ...rest?: string[]]; // rest+optional disallowed
>OptRest : Symbol(OptRest, Decl(namedTupleMembersErrors.ts, 10, 62))
>OptRest : Symbol(OptRest, Decl(namedTupleMembersErrors.ts, 13, 62))

export type NonArrayRest = [first: string, ...rest: number]; // non-arraylike rest, disallowed
>NonArrayRest : Symbol(NonArrayRest, Decl(namedTupleMembersErrors.ts, 12, 58))
>NonArrayRest : Symbol(NonArrayRest, Decl(namedTupleMembersErrors.ts, 15, 58))

export type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled];
>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 14, 60))
>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 14, 60))
>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 17, 60))
>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 17, 60))

export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above
>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 16, 71))
>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 16, 71))
>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71))
>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71))

9 changes: 9 additions & 0 deletions tests/baselines/reference/namedTupleMembersErrors.types
Expand Up @@ -2,12 +2,21 @@
export type Segment1 = [length: number, number]; // partially named, disallowed
>Segment1 : Segment1

export type Segment2 = [number, size: number]; // partially named, disallowed
>Segment2 : Segment2

export type List = [item: any, ...any]; // partially named, disallowed
>List : [any, ...any[]]

export type List2 = [any, ...remainder: any]; // partially named, disallowed
>List2 : [any, ...any[]]

export type Pair = [item: any, any?]; // partially named, disallowed
>Pair : Pair

export type Pair2 = [any, last?: any]; // partially named, disallowed
>Pair2 : Pair2

export type Opt = [element: string?]; // question mark on element disallowed
>Opt : Opt

Expand Down
@@ -1,10 +1,13 @@
// @declaration: true

export type Segment1 = [length: number, number]; // partially named, disallowed
export type Segment2 = [number, size: number]; // partially named, disallowed

export type List = [item: any, ...any]; // partially named, disallowed
export type List2 = [any, ...remainder: any]; // partially named, disallowed

export type Pair = [item: any, any?]; // partially named, disallowed
export type Pair2 = [any, last?: any]; // partially named, disallowed

export type Opt = [element: string?]; // question mark on element disallowed

Expand Down