@@ -4563,14 +4563,24 @@ namespace ts {
4563
4563
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
4564
4564
const hasRestElement = (<TupleType>type.target).hasRestElement;
4565
4565
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
- }
4571
4566
if ((type.target as TupleType).labeledElementDeclarations) {
4572
4567
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]);
4574
4584
}
4575
4585
}
4576
4586
const tupleTypeNode = setEmitFlags(createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine);
@@ -12092,18 +12102,22 @@ namespace ts {
12092
12102
return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]);
12093
12103
}
12094
12104
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);
12097
12111
}
12098
12112
12099
12113
function getArrayOrTupleTargetType(node: ArrayTypeNode | TupleTypeNode): GenericType {
12100
12114
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]) ) {
12102
12116
return readonly ? globalReadonlyArrayType : globalArrayType;
12103
12117
}
12104
12118
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;
12107
12121
const missingName = some(node.elements, e => e.kind !== SyntaxKind.NamedTupleMember);
12108
12122
return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : node.elements as readonly NamedTupleMember[]);
12109
12123
}
@@ -13855,6 +13869,21 @@ namespace ts {
13855
13869
return links.resolvedType;
13856
13870
}
13857
13871
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
+
13858
13887
function getTypeFromTypeNode(node: TypeNode): Type {
13859
13888
return getConditionalFlowTypeOfType(getTypeFromTypeNodeWorker(node), node);
13860
13889
}
@@ -13913,8 +13942,9 @@ namespace ts {
13913
13942
return getTypeFromJSDocNullableTypeNode(<JSDocNullableType>node);
13914
13943
case SyntaxKind.JSDocOptionalType:
13915
13944
return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type));
13916
- case SyntaxKind.ParenthesizedType:
13917
13945
case SyntaxKind.NamedTupleMember:
13946
+ return getTypeFromNamedTupleTypeNode(node as NamedTupleMember);
13947
+ case SyntaxKind.ParenthesizedType:
13918
13948
case SyntaxKind.JSDocNonNullableType:
13919
13949
case SyntaxKind.JSDocTypeExpression:
13920
13950
return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember>node).type);
@@ -30142,16 +30172,15 @@ namespace ts {
30142
30172
let seenOptionalElement = false;
30143
30173
let seenNamedElement = false;
30144
30174
for (let i = 0; i < elementTypes.length; i++) {
30145
- let e = elementTypes[i];
30175
+ const e = elementTypes[i];
30146
30176
if (e.kind === SyntaxKind.NamedTupleMember) {
30147
30177
seenNamedElement = true;
30148
- e = (e as NamedTupleMember).type;
30149
30178
}
30150
30179
else if (seenNamedElement) {
30151
30180
grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_not_have_names);
30152
30181
break;
30153
30182
}
30154
- if (e.kind === SyntaxKind.RestType ) {
30183
+ if (isTupleRestElement(e) ) {
30155
30184
if (i !== elementTypes.length - 1) {
30156
30185
grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type);
30157
30186
break;
@@ -30160,7 +30189,7 @@ namespace ts {
30160
30189
error(e, Diagnostics.A_rest_element_type_must_be_an_array_type);
30161
30190
}
30162
30191
}
30163
- else if (e.kind === SyntaxKind.OptionalType ) {
30192
+ else if (isTupleOptionalElement(e) ) {
30164
30193
seenOptionalElement = true;
30165
30194
}
30166
30195
else if (seenOptionalElement) {
@@ -30255,11 +30284,14 @@ namespace ts {
30255
30284
}
30256
30285
30257
30286
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);
30260
30292
}
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 );
30263
30295
}
30264
30296
checkSourceElement(node.type);
30265
30297
getTypeFromTypeNode(node);
0 commit comments