@@ -800,6 +800,7 @@ import {
800
800
LiteralTypeNode,
801
801
mangleScopedPackageName,
802
802
map,
803
+ mapAllOrFail,
803
804
mapDefined,
804
805
MappedSymbol,
805
806
MappedType,
@@ -6884,21 +6885,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6884
6885
const arity = getTypeReferenceArity(type);
6885
6886
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
6886
6887
if (tupleConstituentNodes) {
6887
- if ((type.target as TupleType).labeledElementDeclarations) {
6888
- for (let i = 0; i < tupleConstituentNodes.length; i++) {
6889
- const flags = (type.target as TupleType).elementFlags[i];
6888
+ const { labeledElementDeclarations } = type.target as TupleType;
6889
+ for (let i = 0; i < tupleConstituentNodes.length; i++) {
6890
+ const flags = (type.target as TupleType).elementFlags[i];
6891
+ const labeledElementDeclaration = labeledElementDeclarations?.[i];
6892
+
6893
+ if (labeledElementDeclaration) {
6890
6894
tupleConstituentNodes[i] = factory.createNamedTupleMember(
6891
6895
flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined,
6892
- factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))),
6896
+ factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]! ))),
6893
6897
flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
6894
6898
flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) :
6895
6899
tupleConstituentNodes[i]
6896
6900
);
6897
6901
}
6898
- }
6899
- else {
6900
- for (let i = 0; i < Math.min(arity, tupleConstituentNodes.length); i++) {
6901
- const flags = (type.target as TupleType).elementFlags[i];
6902
+ else {
6902
6903
tupleConstituentNodes[i] =
6903
6904
flags & ElementFlags.Variable ? factory.createRestTypeNode(flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) :
6904
6905
flags & ElementFlags.Optional ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) :
@@ -12643,19 +12644,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12643
12644
function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] {
12644
12645
if (signatureHasRestParameter(sig)) {
12645
12646
const restIndex = sig.parameters.length - 1;
12647
+ const restName = sig.parameters[restIndex].escapedName;
12646
12648
const restType = getTypeOfSymbol(sig.parameters[restIndex]);
12647
12649
if (isTupleType(restType)) {
12648
- return [expandSignatureParametersWithTupleMembers(restType, restIndex)];
12650
+ return [expandSignatureParametersWithTupleMembers(restType, restIndex, restName )];
12649
12651
}
12650
12652
else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) {
12651
- return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex));
12653
+ return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex, restName ));
12652
12654
}
12653
12655
}
12654
12656
return [sig.parameters];
12655
12657
12656
- function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
12658
+ function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number, restName: __String ) {
12657
12659
const elementTypes = getTypeArguments(restType);
12658
- const associatedNames = getUniqAssociatedNamesFromTupleType(restType);
12660
+ const associatedNames = getUniqAssociatedNamesFromTupleType(restType, restName );
12659
12661
const restParams = map(elementTypes, (t, i) => {
12660
12662
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
12661
12663
const name = associatedNames && associatedNames[i] ? associatedNames[i] :
@@ -12670,10 +12672,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12670
12672
return concatenate(sig.parameters.slice(0, restIndex), restParams);
12671
12673
}
12672
12674
12673
- function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference) {
12675
+ function getUniqAssociatedNamesFromTupleType(type: TupleTypeReference, restName: __String ) {
12674
12676
const associatedNamesMap = new Map<__String, number>();
12675
- return map(type.target.labeledElementDeclarations, labeledElement => {
12676
- const name = getTupleElementLabel(labeledElement);
12677
+ return map(type.target.labeledElementDeclarations, ( labeledElement, i) => {
12678
+ const name = getTupleElementLabel(labeledElement, i, restName );
12677
12679
const prevCounter = associatedNamesMap.get(name);
12678
12680
if (prevCounter === undefined) {
12679
12681
associatedNamesMap.set(name, 1);
@@ -15890,8 +15892,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15890
15892
return readonly ? globalReadonlyArrayType : globalArrayType;
15891
15893
}
15892
15894
const elementFlags = map((node as TupleTypeNode).elements, getTupleElementFlags);
15893
- const missingName = some((node as TupleTypeNode).elements, e => e.kind !== SyntaxKind.NamedTupleMember);
15894
- return getTupleTargetType(elementFlags, readonly, /*associatedNames*/ missingName ? undefined : (node as TupleTypeNode).elements as readonly NamedTupleMember[]);
15895
+ return getTupleTargetType(elementFlags, readonly, map((node as TupleTypeNode).elements, memberIfLabeledElementDeclaration));
15896
+ }
15897
+
15898
+ function memberIfLabeledElementDeclaration(member: Node): NamedTupleMember | ParameterDeclaration | undefined{
15899
+ return isNamedTupleMember(member) || isParameter(member) ? member : undefined;
15895
15900
}
15896
15901
15897
15902
// Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -15981,21 +15986,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15981
15986
return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword;
15982
15987
}
15983
15988
15984
- function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]) {
15989
+ function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration | undefined )[]) {
15985
15990
const tupleTarget = getTupleTargetType(elementFlags || map(elementTypes, _ => ElementFlags.Required), readonly, namedMemberDeclarations);
15986
15991
return tupleTarget === emptyGenericType ? emptyObjectType :
15987
15992
elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) :
15988
15993
tupleTarget;
15989
15994
}
15990
15995
15991
- function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]): GenericType {
15996
+ function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration | undefined )[]): GenericType {
15992
15997
if (elementFlags.length === 1 && elementFlags[0] & ElementFlags.Rest) {
15993
15998
// [...X[]] is equivalent to just X[]
15994
15999
return readonly ? globalReadonlyArrayType : globalArrayType;
15995
16000
}
16001
+ const memberIds = namedMemberDeclarations?.length && mapAllOrFail(namedMemberDeclarations, node => node ? getNodeId(node) : undefined);
15996
16002
const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() +
15997
16003
(readonly ? "R" : "") +
15998
- (namedMemberDeclarations && namedMemberDeclarations.length ? "," + map(namedMemberDeclarations, getNodeId) .join(",") : "");
16004
+ (memberIds ? "," + memberIds .join(",") : "");
15999
16005
let type = tupleTypes.get(key);
16000
16006
if (!type) {
16001
16007
tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations));
@@ -16010,7 +16016,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16010
16016
//
16011
16017
// Note that the generic type created by this function has no symbol associated with it. The same
16012
16018
// is true for each of the synthesized type parameters.
16013
- function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType {
16019
+ function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration | undefined )[] | undefined): TupleType {
16014
16020
const arity = elementFlags.length;
16015
16021
const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic)));
16016
16022
let typeParameters: TypeParameter[] | undefined;
@@ -34513,7 +34519,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34513
34519
return type;
34514
34520
}
34515
34521
34516
- function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
34522
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember): __String;
34523
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index: number, restParameterName?: __String): __String;
34524
+ function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember | undefined, index?: number, restParameterName = "arg" as __String) {
34525
+ if (!d) {
34526
+ return `${restParameterName}_${index}` as __String;
34527
+ }
34517
34528
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
34518
34529
return d.name.escapedText;
34519
34530
}
@@ -34528,7 +34539,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
34528
34539
if (isTupleType(restType)) {
34529
34540
const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
34530
34541
const index = pos - paramCount;
34531
- return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as __String ;
34542
+ return getTupleElementLabel(associatedNames?. [index], index, restParameter.escapedName) ;
34532
34543
}
34533
34544
return restParameter.escapedName;
34534
34545
}
@@ -38531,12 +38542,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
38531
38542
const elementTypes = node.elements;
38532
38543
let seenOptionalElement = false;
38533
38544
let seenRestElement = false;
38534
- const hasNamedElement = some(elementTypes, isNamedTupleMember);
38535
38545
for (const e of elementTypes) {
38536
- if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
38537
- grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
38538
- break;
38539
- }
38540
38546
const flags = getTupleElementFlags(e);
38541
38547
if (flags & ElementFlags.Variadic) {
38542
38548
const type = getTypeFromTypeNode((e as RestTypeNode | NamedTupleMember).type);
0 commit comments