diff --git a/packages/eslint-plugin-solid/src/rules/reactivity.ts b/packages/eslint-plugin-solid/src/rules/reactivity.ts index a9e8116..f0a22af 100644 --- a/packages/eslint-plugin-solid/src/rules/reactivity.ts +++ b/packages/eslint-plugin-solid/src/rules/reactivity.ts @@ -3,7 +3,13 @@ * @link https://github.com/solidjs-community/eslint-plugin-solid/blob/main/docs/reactivity.md */ -import { TSESTree as T, TSESLint, ESLintUtils, ASTUtils } from "@typescript-eslint/utils"; +import { + TSESTree as T, + TSESLint, + ESLintUtils, + ASTUtils, + AST_NODE_TYPES, +} from "@typescript-eslint/utils"; import { traverse } from "estraverse"; import { findParent, @@ -209,6 +215,19 @@ const getNthDestructuredVar = (id: T.Node, n: number, context: CompatContext): V if (el?.type === "Identifier") { return findVariable(context, el); } + } else if (id?.type === "ObjectPattern") { + // {0: a, '1': b, 2: c, ...rest} + const el = id.properties.find((p): p is T.Property => { + if (p.type !== "Property") return false; + if (p.key.type !== "Literal") return false; + + const key = p.key; + return key.value === n || (typeof key.value === "string" && key.value === String(n)); + }); + + if (el?.type === "Property" && el.value.type === "Identifier") { + return findVariable(context, el.value); + } } return null; }; diff --git a/packages/eslint-plugin-solid/test/rules/reactivity.test.ts b/packages/eslint-plugin-solid/test/rules/reactivity.test.ts index f093a84..c5b0ab0 100644 --- a/packages/eslint-plugin-solid/test/rules/reactivity.test.ts +++ b/packages/eslint-plugin-solid/test/rules/reactivity.test.ts @@ -180,6 +180,16 @@ export const cases = run("reactivity", rule, { element.addEventListener("click", () => { console.log(signal()); }, { once: true });`, + `const {0: signal, 1: setSignal} = createSignal(1); + const element = document.getElementById("id"); + element.onclick = () => { + console.log(signal()); + };`, + `const {'0': signal, '1': setSignal} = createSignal(1); + const element = document.getElementById("id"); + element.onclick = () => { + console.log(signal()); + };`, `const [signal, setSignal] = createSignal(1); const element = document.getElementById("id"); element.onclick = () => { @@ -222,6 +232,10 @@ export const cases = run("reactivity", rule, { const [count, setCount] = useSignal(props.initialCount); return
{count()}
; }`, + `function Component(props) { + const {0: count, 1: setCount} = useSignal(props.initialCount); + return
{count()}
; + }`, `function Component(props) { const [count, setCount] = useSignal(props.defaultCount); return
{count()}
; @@ -234,6 +248,13 @@ export const cases = run("reactivity", rule, { return state.firstName + " " + state.lastName; } });`, + `const {0: state, 1: setState} = createStore({ + firstName: 'Will', + lastName: 'Smith', + get fullName() { + return state.firstName + " " + state.lastName; + } + });`, // untrack() `const [signal] = createSignal(5); untrack(() => { @@ -568,6 +589,19 @@ export const cases = run("reactivity", rule, { }, ], }, + { + code: ` + const Component = () => { + const {2: signal, 3: setSignal} = createSignal(); + }`, + errors: [ + { + messageId: "shouldDestructure", + data: { nth: "first " }, + type: T.ObjectPattern, + }, + ], + }, { code: ` const Component = () => {