isAssignmentTarget
x = …, x += …, x++, [x] = …, ({ x } = …), for (x of …)
import { isArrayLiteralExpression as ts_isArrayLiteralExpression, isAsExpression as ts_isAsExpression, isBinaryExpression as ts_isBinaryExpression, isForInStatement as ts_isForInStatement, isForOfStatement as ts_isForOfStatement, isNonNullExpression as ts_isNonNullExpression, isObjectLiteralExpression as ts_isObjectLiteralExpression, isParenthesizedExpression as ts_isParenthesizedExpression, isPostfixUnaryExpression as ts_isPostfixUnaryExpression, isPrefixUnaryExpression as ts_isPrefixUnaryExpression, isPropertyAssignment as ts_isPropertyAssignment, isSatisfiesExpression as ts_isSatisfiesExpression, isShorthandPropertyAssignment as ts_isShorthandPropertyAssignment, isSpreadAssignment as ts_isSpreadAssignment, isSpreadElement as ts_isSpreadElement, isTypeAssertion as ts_isTypeAssertionExpression, SyntaxKind as ts_SyntaxKind, } from "typescript/ast"; import type { Node as ts_Node } from "typescript/ast"; export function isAssignmentTarget(node: ts_Node): boolean { let n = node; for (;;) { const p = n.parent; if (ts_isParenthesizedExpression(p) || ts_isNonNullExpression(p) || ts_isAsExpression(p) || ts_isSatisfiesExpression(p) || ts_isTypeAssertionExpression(p)) n = p; else if (ts_isArrayLiteralExpression(p) || ts_isSpreadElement(p) || ts_isSpreadAssignment(p)) n = p; else if (ts_isShorthandPropertyAssignment(p) && p.name === n) n = p.parent; else if (ts_isPropertyAssignment(p) && p.initializer === n) n = p.parent; else break; if (ts_isObjectLiteralExpression(n)) continue; } const p = n.parent; if (ts_isBinaryExpression(p)) return p.left === n && p.operatorToken.kind >= ts_SyntaxKind.FirstAssignment && p.operatorToken.kind <= ts_SyntaxKind.LastAssignment; if (ts_isPrefixUnaryExpression(p) || ts_isPostfixUnaryExpression(p)) return p.operator === ts_SyntaxKind.PlusPlusToken || p.operator === ts_SyntaxKind.MinusMinusToken; if (ts_isForOfStatement(p) || ts_isForInStatement(p)) return p.initializer === n; return false; }