@@ -4563,14 +4563,24 @@ namespace ts {
45634563 const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
45644564 const hasRestElement = (<TupleType>type.target).hasRestElement;
45654565 if (tupleConstituentNodes) {
4566- for (let i = (<TupleType>type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) {
4567- tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
4568- createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
4569- createOptionalTypeNode(tupleConstituentNodes[i]);
4570- }
45714566 if ((type.target as TupleType).labeledElementDeclarations) {
45724567 for (let i = 0; i < tupleConstituentNodes.length; i++) {
4573- tupleConstituentNodes[i] = createNamedTupleMember(createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))), tupleConstituentNodes[i]);
4568+ const isOptionalOrRest = i >= (<TupleType>type.target).minLength;
4569+ const isRest = isOptionalOrRest && hasRestElement && i === arity - 1;
4570+ const isOptional = isOptionalOrRest && !isRest;
4571+ tupleConstituentNodes[i] = createNamedTupleMember(
4572+ isRest ? createToken(SyntaxKind.DotDotDotToken) : undefined,
4573+ createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))),
4574+ isOptional ? createToken(SyntaxKind.QuestionToken) : undefined,
4575+ isRest ? createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]
4576+ );
4577+ }
4578+ }
4579+ else {
4580+ for (let i = (<TupleType>type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) {
4581+ tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
4582+ createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
4583+ createOptionalTypeNode(tupleConstituentNodes[i]);
45744584 }
45754585 }
45764586 const tupleTypeNode = setEmitFlags(createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine);
@@ -12092,18 +12102,22 @@ namespace ts {
1209212102 return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]);
1209312103 }
1209412104
12095- function unwrapNamedTupleMember(node: TypeNode): TypeNode {
12096- return node.kind === SyntaxKind.NamedTupleMember ? (node as NamedTupleMember).type : node;
12105+ function isTupleRestElement(node: TypeNode) {
12106+ return node.kind === SyntaxKind.RestType || (node.kind === SyntaxKind.NamedTupleMember && !!(node as NamedTupleMember).dotDotDotToken);
12107+ }
12108+
12109+ function isTupleOptionalElement(node: TypeNode) {
12110+ return node.kind === SyntaxKind.OptionalType || (node.kind === SyntaxKind.NamedTupleMember && !!(node as NamedTupleMember).questionToken);
1209712111 }
1209812112
1209912113 function getArrayOrTupleTargetType(node: ArrayTypeNode | TupleTypeNode): GenericType {
1210012114 const readonly = isReadonlyTypeOperator(node.parent);
12101- if (node.kind === SyntaxKind.ArrayType || node.elements.length === 1 && node.elements[0].kind === SyntaxKind.RestType ) {
12115+ if (node.kind === SyntaxKind.ArrayType || node.elements.length === 1 && isTupleRestElement( node.elements[0]) ) {
1210212116 return readonly ? globalReadonlyArrayType : globalArrayType;
1210312117 }
1210412118 const lastElement = lastOrUndefined(node.elements);
12105- const restElement = lastElement && unwrapNamedTupleMember (lastElement).kind === SyntaxKind.RestType ? lastElement : undefined;
12106- const minLength = findLastIndex(node.elements, n => unwrapNamedTupleMember (n).kind !== SyntaxKind.OptionalType && n !== restElement) + 1;
12119+ const restElement = lastElement && isTupleRestElement (lastElement) ? lastElement : undefined;
12120+ const minLength = findLastIndex(node.elements, n => !isTupleOptionalElement (n) && n !== restElement) + 1;
1210712121 const missingName = some(node.elements, e => e.kind !== SyntaxKind.NamedTupleMember);
1210812122 return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : node.elements as readonly NamedTupleMember[]);
1210912123 }
@@ -13855,6 +13869,21 @@ namespace ts {
1385513869 return links.resolvedType;
1385613870 }
1385713871
13872+ function getTypeFromNamedTupleTypeNode(node: NamedTupleMember): Type {
13873+ const links = getNodeLinks(node);
13874+ if (!links.resolvedType) {
13875+ let type = getTypeFromTypeNode(node.type);
13876+ if (node.dotDotDotToken) {
13877+ type = getElementTypeOfArrayType(type) || errorType;
13878+ }
13879+ if (node.questionToken && strictNullChecks) {
13880+ type = getOptionalType(type);
13881+ }
13882+ links.resolvedType = type;
13883+ }
13884+ return links.resolvedType;
13885+ }
13886+
1385813887 function getTypeFromTypeNode(node: TypeNode): Type {
1385913888 return getConditionalFlowTypeOfType(getTypeFromTypeNodeWorker(node), node);
1386013889 }
@@ -13913,8 +13942,9 @@ namespace ts {
1391313942 return getTypeFromJSDocNullableTypeNode(<JSDocNullableType>node);
1391413943 case SyntaxKind.JSDocOptionalType:
1391513944 return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type));
13916- case SyntaxKind.ParenthesizedType:
1391713945 case SyntaxKind.NamedTupleMember:
13946+ return getTypeFromNamedTupleTypeNode(node as NamedTupleMember);
13947+ case SyntaxKind.ParenthesizedType:
1391813948 case SyntaxKind.JSDocNonNullableType:
1391913949 case SyntaxKind.JSDocTypeExpression:
1392013950 return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember>node).type);
@@ -30142,16 +30172,15 @@ namespace ts {
3014230172 let seenOptionalElement = false;
3014330173 let seenNamedElement = false;
3014430174 for (let i = 0; i < elementTypes.length; i++) {
30145- let e = elementTypes[i];
30175+ const e = elementTypes[i];
3014630176 if (e.kind === SyntaxKind.NamedTupleMember) {
3014730177 seenNamedElement = true;
30148- e = (e as NamedTupleMember).type;
3014930178 }
3015030179 else if (seenNamedElement) {
3015130180 grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_not_have_names);
3015230181 break;
3015330182 }
30154- if (e.kind === SyntaxKind.RestType ) {
30183+ if (isTupleRestElement(e) ) {
3015530184 if (i !== elementTypes.length - 1) {
3015630185 grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type);
3015730186 break;
@@ -30160,7 +30189,7 @@ namespace ts {
3016030189 error(e, Diagnostics.A_rest_element_type_must_be_an_array_type);
3016130190 }
3016230191 }
30163- else if (e.kind === SyntaxKind.OptionalType ) {
30192+ else if (isTupleOptionalElement(e) ) {
3016430193 seenOptionalElement = true;
3016530194 }
3016630195 else if (seenOptionalElement) {
@@ -30255,11 +30284,14 @@ namespace ts {
3025530284 }
3025630285
3025730286 function checkNamedTupleMember(node: NamedTupleMember) {
30258- if (node.dotDotDotToken) {
30259- grammarErrorOnNode(node, Diagnostics.Rest_tuple_members_are_declared_with_a_on_the_type_A_on_the_name_is_invalid);
30287+ if (node.dotDotDotToken && node.questionToken) {
30288+ grammarErrorOnNode(node, Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest);
30289+ }
30290+ if (node.type.kind === SyntaxKind.OptionalType) {
30291+ grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type);
3026030292 }
30261- if (node.questionToken ) {
30262- grammarErrorOnNode(node, Diagnostics.Tuple_members_express_optionality_with_a_trailing_question_mark_on_the_type_a_question_mark_on_the_member_name_is_invalid );
30293+ if (node.type.kind === SyntaxKind.RestType ) {
30294+ grammarErrorOnNode(node.type , Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type );
3026330295 }
3026430296 checkSourceElement(node.type);
3026530297 getTypeFromTypeNode(node);
0 commit comments