diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1eb750c8939..dc87bb0f33b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31121,6 +31121,7 @@ namespace ts { function checkTupleType(node: TupleTypeNode) { const elementTypes = node.elements; let seenOptionalElement = false; + let seenRestElement = false; const hasNamedElement = some(elementTypes, isNamedTupleMember); for (let i = 0; i < elementTypes.length; i++) { const e = elementTypes[i]; @@ -31130,16 +31131,17 @@ namespace ts { } const flags = getTupleElementFlags(e); if (flags & ElementFlags.Variadic) { - if (!isArrayLikeType(getTypeFromTypeNode((e).type))) { + const type = getTypeFromTypeNode((e).type); + if (!isArrayLikeType(type)) { error(e, Diagnostics.A_rest_element_type_must_be_an_array_type); break; } + if (isArrayType(type) || isTupleType(type) && type.target.combinedFlags & ElementFlags.Rest) { + seenRestElement = true; + } } else if (flags & ElementFlags.Rest) { - if (i !== elementTypes.length - 1) { - grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type); - break; - } + seenRestElement = true; } else if (flags & ElementFlags.Optional) { seenOptionalElement = true; @@ -31148,6 +31150,10 @@ namespace ts { grammarErrorOnNode(e, Diagnostics.A_required_element_cannot_follow_an_optional_element); break; } + if (seenRestElement && i !== elementTypes.length - 1) { + grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type); + break; + } } forEach(node.elements, checkSourceElement); }