Skip to content

Commit cb6a0e7

Browse files
authored
Merge pull request #64 from solidjs-community/fix/destructure-type
Keep type annotations when autofixing destructured props
2 parents 9e0d8ee + 4c46745 commit cb6a0e7

File tree

5 files changed

+34
-8
lines changed

5 files changed

+34
-8
lines changed

docs/no-destructure.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ let Component = (_props) => {
199199
return <div a={props["a" + ""]} b={rest.b} />;
200200
};
201201

202+
let Component = ({ prop1, prop2 }: Props) => <div p1={prop1} p2={prop2} />;
203+
// after eslint --fix:
204+
let Component = (props: Props) => <div p1={props.prop1} p2={props.prop2} />;
205+
202206
```
203207

204208
### Valid Examples
@@ -251,5 +255,7 @@ let Component = (props) => {
251255

252256
let element = <div />;
253257

258+
let Component = (props: Props) => <div />;
259+
254260
```
255261
<!-- AUTO-GENERATED-CONTENT:END -->

src/rules/no-destructure.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,13 @@ const rule: TSESLint.RuleModule<"noDestructure", []> = {
126126

127127
// Replace destructured props with a `props` identifier (`_props` in case of rest params/defaults)
128128
const origProps = !(hasDefaults || rest) ? propsName : "_" + propsName;
129-
fixes.push(fixer.replaceText(props, origProps));
129+
if (props.typeAnnotation) {
130+
// in `{ prop1, prop2 }: Props`, leave `: Props` alone
131+
const range = [props.range[0], props.typeAnnotation.range[0]] as const;
132+
fixes.push(fixer.replaceTextRange(range, origProps));
133+
} else {
134+
fixes.push(fixer.replaceText(props, origProps));
135+
}
130136

131137
const sourceCode = context.getSourceCode();
132138

test/ruleTester.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ const jsxTester = new RuleTester({
2020
},
2121
});
2222

23-
// TypeScript's ESLint parser
24-
const tsTester = new RuleTester({
23+
// spread ...tsOnlyTest into a test case to enforce it always runs with the TS parser
24+
export const tsOnlyTest: Pick<TSESLint.RuleTesterConfig, "parser" | "parserOptions"> = {
2525
parser: require.resolve("@typescript-eslint/parser"),
2626
parserOptions: {
2727
ecmaVersion: 2018,
@@ -30,7 +30,11 @@ const tsTester = new RuleTester({
3030
jsx: true,
3131
},
3232
},
33-
});
33+
};
34+
35+
// TypeScript's ESLint parser
36+
const tsTester = new RuleTester(tsOnlyTest);
37+
3438
// Babel's ESLint parser
3539
const babelTester = new RuleTester({
3640
parser: require.resolve("@babel/eslint-parser"),

test/rules/imports.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { run } from "../ruleTester";
1+
import { run, tsOnlyTest } from "../ruleTester";
22
import rule from "../../src/rules/imports";
33

44
export const cases = run("imports", rule, {
@@ -15,7 +15,7 @@ export const cases = run("imports", rule, {
1515
{
1616
code: `import type { Component, JSX } from "solid-js";
1717
import type { Store } from "solid-js/store";`,
18-
parser: require.resolve("@typescript-eslint/parser"),
18+
...tsOnlyTest,
1919
},
2020
],
2121
invalid: [
@@ -56,7 +56,7 @@ console.log('hi');`,
5656
output: `
5757
import { createSignal, Component } from "solid-js";
5858
console.log('hi');`,
59-
parser: require.resolve("@typescript-eslint/parser"),
59+
...tsOnlyTest,
6060
},
6161
{
6262
code: `import { createSignal } from "solid-js/web";

test/rules/no-destructure.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { run } from "../ruleTester";
1+
import { run, tsOnlyTest } from "../ruleTester";
22
import rule from "../../src/rules/no-destructure";
33

44
export const cases = run("no-destructure", rule, {
@@ -35,6 +35,10 @@ export const cases = run("no-destructure", rule, {
3535
return <div a={a} />;
3636
}`,
3737
`let element = <div />`, // parse top level JSX
38+
{
39+
code: `let Component = (props: Props) => <div />;`,
40+
...tsOnlyTest,
41+
},
3842
],
3943
invalid: [
4044
{
@@ -240,5 +244,11 @@ various();
240244
const [props, rest] = splitProps(mergeProps({ ['a' + '']: 5 }, _props), ['a' + '']); return (<div a={props['a' + '']} b={rest.b} />);
241245
}`,
242246
},
247+
{
248+
code: `let Component = ({ prop1, prop2 }: Props) => <div p1={prop1} p2={prop2} />;`,
249+
errors: [{ messageId: "noDestructure" }],
250+
output: `let Component = (props: Props) => <div p1={props.prop1} p2={props.prop2} />;`,
251+
...tsOnlyTest,
252+
},
243253
],
244254
});

0 commit comments

Comments
 (0)