Skip to content

Added recursive check for nested tuple elements #43567

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33295,13 +33295,32 @@ namespace ts {
checkSourceElement(node.elementType);
}

function checkTupleNamedElement(node: TupleTypeNode, hasNamedElement: boolean): boolean {
for (const e of node.elements) {
if (isRestTypeNode(e) && isTupleTypeNode(e.type)) {
return checkTupleNamedElement(e.type, hasNamedElement);
}
else if (hasNamedElement !== isNamedTupleMember(e)) {
grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
return false;
}
}

return true;
}

function checkTupleType(node: TupleTypeNode) {
const elementTypes = node.elements;
let seenOptionalElement = false;
let seenRestElement = false;
const hasNamedElement = some(elementTypes, isNamedTupleMember);
for (const e of elementTypes) {
if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
if (isRestTypeNode(e) && isTupleTypeNode(e.type)) {
if (!checkTupleNamedElement(e.type, hasNamedElement)) {
break;
}
}
else if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
break;
}
Expand Down
4 changes: 3 additions & 1 deletion tests/baselines/reference/namedTupleMembers.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ declare function getArgsForInjection<T extends (...args: any[]) => any>(x: T): P

export const argumentsOfGAsFirstArgument = f(getArgsForInjection(g)); // one tuple with captures arguments as first member
export const argumentsOfG = f(...getArgsForInjection(g)); // captured arguments list re-spread


export type NestedRest = [foo: number, ...[bar: number, ...[baz: number]]];

//// [namedTupleMembers.js]
"use strict";
Expand Down Expand Up @@ -138,3 +139,4 @@ export declare type RecusiveRest = [first: string, ...rest: RecusiveRest[]];
export declare type RecusiveRest2 = [string, ...RecusiveRest2[]];
export declare const argumentsOfGAsFirstArgument: [[elem: object, index: number]];
export declare const argumentsOfG: [elem: object, index: number];
export declare type NestedRest = [foo: number, ...[bar: number, ...[baz: number]]];
3 changes: 3 additions & 0 deletions tests/baselines/reference/namedTupleMembers.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,6 @@ export const argumentsOfG = f(...getArgsForInjection(g)); // captured arguments
>getArgsForInjection : Symbol(getArgsForInjection, Decl(namedTupleMembers.ts, 72, 56))
>g : Symbol(g, Decl(namedTupleMembers.ts, 71, 48))

export type NestedRest = [foo: number, ...[bar: number, ...[baz: number]]];
>NestedRest : Symbol(NestedRest, Decl(namedTupleMembers.ts, 76, 57))

3 changes: 3 additions & 0 deletions tests/baselines/reference/namedTupleMembers.types
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,6 @@ export const argumentsOfG = f(...getArgsForInjection(g)); // captured arguments
>getArgsForInjection : <T extends (...args: any[]) => any>(x: T) => Parameters<T>
>g : (elem: object, index: number) => object

export type NestedRest = [foo: number, ...[bar: number, ...[baz: number]]];
>NestedRest : [number, number, number]

8 changes: 6 additions & 2 deletions tests/baselines/reference/namedTupleMembersErrors.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(16,39): err
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(23,61): error TS5084: Tuple members must all have names or all not have names.


==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (14 errors) ====
==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (15 errors) ====
export type Segment1 = [length: number, number]; // partially named, disallowed
~~~~~~
!!! error TS5084: Tuple members must all have names or all not have names.
Expand Down Expand Up @@ -64,4 +65,7 @@ tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(21,13): err
export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above
~~~~~~~~~~~~
!!! error TS2456: Type alias 'RecusiveRest' circularly references itself.


export type NestedRest = [foo: number, ...[bar: number, ...[number]]]; // partially named, disallowed
~~~~~~
!!! error TS5084: Tuple members must all have names or all not have names.
4 changes: 3 additions & 1 deletion tests/baselines/reference/namedTupleMembersErrors.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export type NonArrayRest = [first: string, ...rest: number]; // non-arraylike re

export type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled];
export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above


export type NestedRest = [foo: number, ...[bar: number, ...[number]]]; // partially named, disallowed

//// [namedTupleMembersErrors.js]
"use strict";
Expand All @@ -41,3 +42,4 @@ export declare type OptRest = [first: string, ...rest?: string[]];
export declare type NonArrayRest = [first: string, ...rest: number];
export declare type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled];
export declare type RecusiveRest = [first: string, ...rest: RecusiveRest];
export declare type NestedRest = [foo: number, ...[bar: number, ...[number]]];
3 changes: 3 additions & 0 deletions tests/baselines/reference/namedTupleMembersErrors.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as
>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71))
>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71))

export type NestedRest = [foo: number, ...[bar: number, ...[number]]]; // partially named, disallowed
>NestedRest : Symbol(NestedRest, Decl(namedTupleMembersErrors.ts, 20, 66))

3 changes: 3 additions & 0 deletions tests/baselines/reference/namedTupleMembersErrors.types
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ export type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled];
export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above
>RecusiveRest : any

export type NestedRest = [foo: number, ...[bar: number, ...[number]]]; // partially named, disallowed
>NestedRest : [number, number, number]

Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,5 @@ declare function getArgsForInjection<T extends (...args: any[]) => any>(x: T): P

export const argumentsOfGAsFirstArgument = f(getArgsForInjection(g)); // one tuple with captures arguments as first member
export const argumentsOfG = f(...getArgsForInjection(g)); // captured arguments list re-spread

export type NestedRest = [foo: number, ...[bar: number, ...[baz: number]]];
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export type NonArrayRest = [first: string, ...rest: number]; // non-arraylike re

export type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled];
export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above

export type NestedRest = [foo: number, ...[bar: number, ...[number]]]; // partially named, disallowed