@@ -6888,21 +6888,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6888
6888
const arity = getTypeReferenceArity(type);
6889
6889
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
6890
6890
if (tupleConstituentNodes) {
6891
- if ((type.target as TupleType).labeledElementDeclarations) {
6892
- for (let i = 0; i < tupleConstituentNodes.length; i++) {
6893
- const flags = (type.target as TupleType).elementFlags[i];
6891
+ const { labeledElementDeclarations } = type.target as TupleType;
6892
+ for (let i = 0; i < tupleConstituentNodes.length; i++) {
6893
+ const flags = (type.target as TupleType).elementFlags[i];
6894
+ const labeledElementDeclaration = labeledElementDeclarations?.[i];
6895
+
6896
+ if (labeledElementDeclaration) {
6894
6897
tupleConstituentNodes[i] = factory.createNamedTupleMember(
6895
6898
flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined,
6896
- factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i] ))),
6899
+ factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel(labeledElementDeclaration ))),
6897
6900
flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
6898
6901
flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) :
6899
6902
tupleConstituentNodes[i]
6900
6903
);
6901
6904
}
6902
- }
6903
- else {
6904
- for (let i = 0; i < Math.min(arity, tupleConstituentNodes.length); i++) {
6905
- const flags = (type.target as TupleType).elementFlags[i];
6905
+ else {
6906
6906
tupleConstituentNodes[i] =
6907
6907
flags & ElementFlags.Variable ? factory.createRestTypeNode(flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) :
6908
6908
flags & ElementFlags.Optional ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) :
@@ -12657,19 +12657,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12657
12657
function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] {
12658
12658
if (signatureHasRestParameter(sig)) {
12659
12659
const restIndex = sig.parameters.length - 1;
12660
+ const restName = sig.parameters[restIndex].escapedName;
12660
12661
const restType = getTypeOfSymbol(sig.parameters[restIndex]);
12661
12662
if (isTupleType(restType)) {
12662
- return [expandSignatureParametersWithTupleMembers(restType, restIndex)];
12663
+ return [expandSignatureParametersWithTupleMembers(restType, restIndex, restName )];
12663
12664
}
12664
12665
else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) {
12665
- return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex));
12666
+ return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restName ));
12666
12667
}
12667
12668
}
12668
12669
return [sig.parameters];
12669
12670
12670
- function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
12671
- const elementTypes = getElementTypes (restType);
12672
- const associatedNames = getUniqAssociatedNamesFromTupleType(restType);
12671
+ function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number, restName: __String ) {
12672
+ const elementTypes = getTypeArguments (restType);
12673
+ const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restName );
12673
12674
const restParams = map(elementTypes, (t, i) => {
12674
12675
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
12675
12676
const name = associatedNames && associatedNames[i] ? associatedNames[i] :
@@ -12684,10 +12685,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12684
12685
return concatenate(sig.parameters.slice(0, restIndex), restParams);
12685
12686
}
12686
12687
12687
- function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference) {
12688
+ function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restName: __String ) {
12688
12689
const associatedNamesMap = new Map<__String, number>();
12689
- return map(type.target.labeledElementDeclarations, labeledElement => {
12690
- const name = getTupleElementLabel(labeledElement);
12690
+ return map(type.target.labeledElementDeclarations, ( labeledElement, i) => {
12691
+ const name = getTupleElementLabel(labeledElement, i, restName );
12691
12692
const prevCounter = associatedNamesMap.get(name);
12692
12693
if (prevCounter === undefined) {
12693
12694
associatedNamesMap.set(name, 1);
@@ -15963,8 +15964,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15963
15964
return readonly ? globalReadonlyArrayType : globalArrayType;
15964
15965
}
15965
15966
const elementFlags = map((node as TupleTypeNode).elements, getTupleElementFlags);
15966
- const missingName = some((node as TupleTypeNode).elements, e => e.kind !== SyntaxKind.NamedTupleMember);
15967
- return getTupleTargetType(elementFlags, readonly, /*associatedNames*/ missingName ? undefined : (node as TupleTypeNode).elements as readonly NamedTupleMember[]);
15967
+ return getTupleTargetType(elementFlags, readonly, map((node as TupleTypeNode).elements, memberIfLabeledElementDeclaration));
15968
+ }
15969
+
15970
+ function memberIfLabeledElementDeclaration(member: Node): NamedTupleMember | ParameterDeclaration | undefined {
15971
+ return isNamedTupleMember(member) || isParameter(member) ? member : undefined;
15968
15972
}
15969
15973
15970
15974
// Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -16054,21 +16058,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16054
16058
return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword;
16055
16059
}
16056
16060
16057
- function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations? : readonly (NamedTupleMember | ParameterDeclaration) []) {
16061
+ function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[] = []) {
16058
16062
const tupleTarget = getTupleTargetType(elementFlags || map(elementTypes, _ => ElementFlags.Required), readonly, namedMemberDeclarations);
16059
16063
return tupleTarget === emptyGenericType ? emptyObjectType :
16060
16064
elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) :
16061
16065
tupleTarget;
16062
16066
}
16063
16067
16064
- function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations? : readonly (NamedTupleMember | ParameterDeclaration)[]): GenericType {
16068
+ function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined )[]): GenericType {
16065
16069
if (elementFlags.length === 1 && elementFlags[0] & ElementFlags.Rest) {
16066
16070
// [...X[]] is equivalent to just X[]
16067
16071
return readonly ? globalReadonlyArrayType : globalArrayType;
16068
16072
}
16073
+ const memberIds = mapDefined(namedMemberDeclarations, node => node ? getNodeId(node) : undefined);
16069
16074
const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() +
16070
16075
(readonly ? "R" : "") +
16071
- (namedMemberDeclarations && namedMemberDeclarations .length ? "," + map(namedMemberDeclarations, getNodeId) .join(",") : "");
16076
+ (memberIds .length ? "," + memberIds .join(",") : "");
16072
16077
let type = tupleTypes.get(key);
16073
16078
if (!type) {
16074
16079
tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations));
@@ -16083,7 +16088,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16083
16088
//
16084
16089
// Note that the generic type created by this function has no symbol associated with it. The same
16085
16090
// is true for each of the synthesized type parameters.
16086
- function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType {
16091
+ function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined)[] ): TupleType {
16087
16092
const arity = elementFlags.length;
16088
16093
const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic)));
16089
16094
let typeParameters: TypeParameter[] | undefined;
@@ -16165,7 +16170,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16165
16170
// In either layout, zero or more generic variadic elements may be present at any location.
16166
16171
const expandedTypes: Type[] = [];
16167
16172
const expandedFlags: ElementFlags[] = [];
16168
- let expandedDeclarations: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
16173
+ const expandedDeclarations: (NamedTupleMember | ParameterDeclaration | undefined)[] = [];
16169
16174
let lastRequiredIndex = -1;
16170
16175
let firstRestIndex = -1;
16171
16176
let lastOptionalOrRestIndex = -1;
@@ -16208,7 +16213,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16208
16213
(t, i) => expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t));
16209
16214
expandedTypes.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
16210
16215
expandedFlags.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
16211
- expandedDeclarations? .splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
16216
+ expandedDeclarations.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
16212
16217
}
16213
16218
const tupleTarget = getTupleTargetType(expandedFlags, target.readonly, expandedDeclarations);
16214
16219
return tupleTarget === emptyGenericType ? emptyObjectType :
@@ -16227,12 +16232,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16227
16232
}
16228
16233
expandedTypes.push(flags & ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type);
16229
16234
expandedFlags.push(flags);
16230
- if (expandedDeclarations && declaration) {
16231
- expandedDeclarations.push(declaration);
16232
- }
16233
- else {
16234
- expandedDeclarations = undefined;
16235
- }
16235
+ expandedDeclarations.push(declaration);
16236
16236
}
16237
16237
}
16238
16238
@@ -34828,7 +34828,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34828
34828
return type;
34829
34829
}
34830
34830
34831
- function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
34831
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String;
34832
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restParameterName?: __String): __String;
34833
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index?: number, restParameterName = "arg" as __String) {
34834
+ if (!d) {
34835
+ return `${restParameterName}_${index}` as __String;
34836
+ }
34832
34837
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
34833
34838
return d.name.escapedText;
34834
34839
}
@@ -34843,7 +34848,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34843
34848
if (isTupleType(restType)) {
34844
34849
const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
34845
34850
const index = pos - paramCount;
34846
- return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as __String ;
34851
+ return getTupleElementLabel(associatedNames?. [index], index, restParameter.escapedName) ;
34847
34852
}
34848
34853
return restParameter.escapedName;
34849
34854
}
@@ -38870,12 +38875,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
38870
38875
const elementTypes = node.elements;
38871
38876
let seenOptionalElement = false;
38872
38877
let seenRestElement = false;
38873
- const hasNamedElement = some(elementTypes, isNamedTupleMember);
38874
38878
for (const e of elementTypes) {
38875
- if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
38876
- grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
38877
- break;
38878
- }
38879
38879
const flags = getTupleElementFlags(e);
38880
38880
if (flags & ElementFlags.Variadic) {
38881
38881
const type = getTypeFromTypeNode((e as RestTypeNode | NamedTupleMember).type);
0 commit comments