diff --git a/packages/babel-types/src/clone/cloneNode.js b/packages/babel-types/src/clone/cloneNode.js index 6e43d191aa66..1da6c930e040 100644 --- a/packages/babel-types/src/clone/cloneNode.js +++ b/packages/babel-types/src/clone/cloneNode.js @@ -37,6 +37,12 @@ export default function cloneNode(node: T, deep: boolean = true): T { // Special-case identifiers since they are the most cloned nodes. if (type === "Identifier") { newNode.name = node.name; + + if (has(node, "typeAnnotation")) { + newNode.typeAnnotation = deep + ? cloneIfNodeOrArray(node.typeAnnotation, true) + : node.typeAnnotation; + } } else if (!has(NODE_FIELDS, type)) { throw new Error(`Unknown node type: "${type}"`); } else { diff --git a/packages/babel-types/test/cloning.js b/packages/babel-types/test/cloning.js index 0ad43fbfd781..83e7c70491e0 100644 --- a/packages/babel-types/test/cloning.js +++ b/packages/babel-types/test/cloning.js @@ -56,4 +56,20 @@ describe("cloneNode", function() { expect(node.object).toBe(cloned.object); expect(node.property).toBe(cloned.property); }); + + it("should preserve type annotations", function() { + const node = t.variableDeclaration("let", [ + t.variableDeclarator({ + ...t.identifier("value"), + typeAnnotation: t.anyTypeAnnotation(), + }), + ]); + const cloned = t.cloneNode(node, /* deep */ true); + expect(cloned.declarations[0].id.typeAnnotation).toEqual( + node.declarations[0].id.typeAnnotation, + ); + expect(cloned.declarations[0].id.typeAnnotation).not.toBe( + node.declarations[0].id.typeAnnotation, + ); + }); });