@@ -1015,6 +1015,7 @@ namespace ts {
10151015 const potentialNewTargetCollisions: Node[] = [];
10161016 const potentialWeakMapSetCollisions: Node[] = [];
10171017 const potentialReflectCollisions: Node[] = [];
1018+ const potentialUnusedRenamedBindingElementsInTypes: BindingElement[] = [];
10181019 const awaitedTypeStack: number[] = [];
10191020
10201021 const diagnostics = createDiagnosticCollection();
@@ -5945,19 +5946,29 @@ namespace ts {
59455946 return parameterNode;
59465947
59475948 function cloneBindingName(node: BindingName): BindingName {
5948- return elideInitializerAndSetEmitFlags (node) as BindingName;
5949- function elideInitializerAndSetEmitFlags (node: Node): Node {
5949+ return elideInitializerAndPropertyRenamingAndSetEmitFlags (node) as BindingName;
5950+ function elideInitializerAndPropertyRenamingAndSetEmitFlags (node: Node): Node {
59505951 if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
59515952 trackComputedName(node.expression, context.enclosingDeclaration, context);
59525953 }
5953- let visited = visitEachChild(node, elideInitializerAndSetEmitFlags , nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags )!;
5954+ let visited = visitEachChild(node, elideInitializerAndPropertyRenamingAndSetEmitFlags , nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndPropertyRenamingAndSetEmitFlags )!;
59545955 if (isBindingElement(visited)) {
5955- visited = factory.updateBindingElement(
5956- visited,
5957- visited.dotDotDotToken,
5958- visited.propertyName,
5959- visited.name,
5960- /*initializer*/ undefined);
5956+ if (visited.propertyName && isIdentifier(visited.propertyName) && isIdentifier(visited.name)) {
5957+ visited = factory.updateBindingElement(
5958+ visited,
5959+ visited.dotDotDotToken,
5960+ /* propertyName*/ undefined,
5961+ visited.propertyName,
5962+ /*initializer*/ undefined);
5963+ }
5964+ else {
5965+ visited = factory.updateBindingElement(
5966+ visited,
5967+ visited.dotDotDotToken,
5968+ visited.propertyName,
5969+ visited.name,
5970+ /*initializer*/ undefined);
5971+ }
59615972 }
59625973 if (!nodeIsSynthesized(visited)) {
59635974 visited = factory.cloneNode(visited);
@@ -37432,6 +37443,24 @@ namespace ts {
3743237443 });
3743337444 }
3743437445
37446+ function checkPotentialUncheckedRenamedBindingElementsInTypes() {
37447+ for (const node of potentialUnusedRenamedBindingElementsInTypes) {
37448+ if (!getSymbolOfNode(node)?.isReferenced) {
37449+ const wrappingDeclaration = walkUpBindingElementsAndPatterns(node);
37450+ Debug.assert(isParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here");
37451+ const diagnostic = createDiagnosticForNode(node.name, Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, declarationNameToString(node.name), declarationNameToString(node.propertyName));
37452+ if (!wrappingDeclaration.type) {
37453+ // entire parameter does not have type annotation, suggest adding an annotation
37454+ addRelatedInfo(
37455+ diagnostic,
37456+ createFileDiagnostic(getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 1, Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, declarationNameToString(node.propertyName))
37457+ );
37458+ }
37459+ diagnostics.add(diagnostic);
37460+ }
37461+ }
37462+ }
37463+
3743537464 function bindingNameText(name: BindingName): string {
3743637465 switch (name.kind) {
3743737466 case SyntaxKind.Identifier:
@@ -37773,6 +37802,19 @@ namespace ts {
3777337802 }
3777437803
3777537804 if (isBindingElement(node)) {
37805+ if (
37806+ node.propertyName &&
37807+ isIdentifier(node.name) &&
37808+ isParameterDeclaration(node) &&
37809+ nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) {
37810+ // type F = ({a: string}) => void;
37811+ // ^^^^^^
37812+ // variable renaming in function type notation is confusing,
37813+ // so we forbid it even if noUnusedLocals is not enabled
37814+ potentialUnusedRenamedBindingElementsInTypes.push(node);
37815+ return;
37816+ }
37817+
3777637818 if (isObjectBindingPattern(node.parent) && node.dotDotDotToken && languageVersion < ScriptTarget.ES2018) {
3777737819 checkExternalEmitHelpers(node, ExternalEmitHelpers.Rest);
3777837820 }
@@ -41617,6 +41659,7 @@ namespace ts {
4161741659 clear(potentialNewTargetCollisions);
4161841660 clear(potentialWeakMapSetCollisions);
4161941661 clear(potentialReflectCollisions);
41662+ clear(potentialUnusedRenamedBindingElementsInTypes);
4162041663
4162141664 forEach(node.statements, checkSourceElement);
4162241665 checkSourceElement(node.endOfFileToken);
@@ -41636,6 +41679,9 @@ namespace ts {
4163641679 }
4163741680 });
4163841681 }
41682+ if (!node.isDeclarationFile) {
41683+ checkPotentialUncheckedRenamedBindingElementsInTypes();
41684+ }
4163941685 });
4164041686
4164141687 if (compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error &&
0 commit comments