Skip to content

Commit 5811f4d

Browse files
committed
fix(linter/array-type): false negative with arrays in generic args
1 parent 2401976 commit 5811f4d

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

crates/oxc_linter/src/rules/typescript/array_type.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ impl Rule for ArrayType {
215215
ctx,
216216
);
217217
}
218+
AstKind::TSTypeParameterInstantiation(ts_type_param_instantiation) => {
219+
for param in &ts_type_param_instantiation.params {
220+
check(param, default_config, readonly_config, ctx);
221+
}
222+
}
218223
_ => {}
219224
}
220225
}
@@ -1256,6 +1261,36 @@ fn test() {
12561261
("type x = Array<number>[]", None),
12571262
("const arr: Array<Array<number>>[] = [];", None),
12581263
("export function fn4(arr: Array<number>[]) { return arr; }", None),
1264+
(
1265+
"function testFn<T>(param: T) { return param; }
1266+
export const test2 = testFn<{name: string}[]>([]);",
1267+
Some(serde_json::json!([{"default":"array-simple"}])),
1268+
),
1269+
(
1270+
"function testFn<T>(param: T) { return param; }
1271+
export const test2 = testFn<Array<{name: string}>>([]);",
1272+
Some(serde_json::json!([{"default":"array"}])),
1273+
),
1274+
(
1275+
"function testFn<T>(param: T) { return param; }
1276+
export const test2 = testFn<string[]>([]);",
1277+
Some(serde_json::json!([{"default":"generic"}])),
1278+
),
1279+
(
1280+
"function testFn<T>(param: T) { return param; }
1281+
export const test2 = testFn<(string | number)[]>([]);",
1282+
Some(serde_json::json!([{"default":"generic"}])),
1283+
),
1284+
(
1285+
"function testFn<T>(param: T) { return param; }
1286+
export const test2 = testFn<readonly string[]>([]);",
1287+
Some(serde_json::json!([{"default":"generic"}])),
1288+
),
1289+
(
1290+
"function testFn<T>(param: T) { return param; }
1291+
export const test2 = testFn<ReadonlyArray<string>>([]);",
1292+
Some(serde_json::json!([{"default":"array"}])),
1293+
),
12591294
];
12601295

12611296
let fix: Vec<(&str, &str, Option<serde_json::Value>)> = vec![
@@ -1788,6 +1823,48 @@ fn test() {
17881823
"let a: Promise<Array<string>> = Promise.resolve([]);",
17891824
Some(serde_json::json!([{"default": "generic"}])),
17901825
),
1826+
(
1827+
"function testFn<T>(param: T) { return param; }
1828+
export const test2 = testFn<{name: string}[]>([]);",
1829+
"function testFn<T>(param: T) { return param; }
1830+
export const test2 = testFn<Array<{name: string}>>([]);",
1831+
Some(serde_json::json!([{"default":"array-simple"}])),
1832+
),
1833+
(
1834+
"function testFn<T>(param: T) { return param; }
1835+
export const test2 = testFn<Array<{name: string}>>([]);",
1836+
"function testFn<T>(param: T) { return param; }
1837+
export const test2 = testFn<{name: string}[]>([]);",
1838+
Some(serde_json::json!([{"default":"array"}])),
1839+
),
1840+
(
1841+
"function testFn<T>(param: T) { return param; }
1842+
export const test2 = testFn<string[]>([]);",
1843+
"function testFn<T>(param: T) { return param; }
1844+
export const test2 = testFn<Array<string>>([]);",
1845+
Some(serde_json::json!([{"default":"generic"}])),
1846+
),
1847+
(
1848+
"function testFn<T>(param: T) { return param; }
1849+
export const test2 = testFn<(string | number)[]>([]);",
1850+
"function testFn<T>(param: T) { return param; }
1851+
export const test2 = testFn<Array<string | number>>([]);",
1852+
Some(serde_json::json!([{"default":"generic"}])),
1853+
),
1854+
(
1855+
"function testFn<T>(param: T) { return param; }
1856+
export const test2 = testFn<readonly string[]>([]);",
1857+
"function testFn<T>(param: T) { return param; }
1858+
export const test2 = testFn<ReadonlyArray<string>>([]);",
1859+
Some(serde_json::json!([{"default":"generic"}])),
1860+
),
1861+
(
1862+
"function testFn<T>(param: T) { return param; }
1863+
export const test2 = testFn<ReadonlyArray<string>>([]);",
1864+
"function testFn<T>(param: T) { return param; }
1865+
export const test2 = testFn<readonly string[]>([]);",
1866+
Some(serde_json::json!([{"default":"array"}])),
1867+
),
17911868
];
17921869

17931870
Tester::new(ArrayType::NAME, ArrayType::PLUGIN, pass, fail)

crates/oxc_linter/src/snapshots/typescript_array_type.snap

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,13 @@ source: crates/oxc_linter/src/tester.rs
652652
╰────
653653
help: Replace `string[]` with `Array<string>`.
654654

655+
⚠ typescript-eslint(array-type): Array type using 'string[]' is forbidden. Use 'Array<string>' instead.
656+
╭─[array_type.ts:1:16]
657+
1 │ let a: Promise<string[]> = Promise.resolve([]);
658+
· ────────
659+
╰────
660+
help: Replace `string[]` with `Array<string>`.
661+
655662
⚠ typescript-eslint(array-type): Array type using 'Array<number>' is forbidden. Use 'number[]' instead.
656663
╭─[array_type.ts:1:10]
657664
1 │ type x = Array<number>[]
@@ -666,9 +673,64 @@ source: crates/oxc_linter/src/tester.rs
666673
╰────
667674
help: Replace `Array<Array<number>>` with `Array<number>[]`.
668675

676+
⚠ typescript-eslint(array-type): Array type using 'Array<number>' is forbidden. Use 'number[]' instead.
677+
╭─[array_type.ts:1:18]
678+
1 │ const arr: Array<Array<number>>[] = [];
679+
· ─────────────
680+
╰────
681+
help: Replace `Array<number>` with `number[]`.
682+
669683
⚠ typescript-eslint(array-type): Array type using 'Array<number>' is forbidden. Use 'number[]' instead.
670684
╭─[array_type.ts:1:26]
671685
1 │ export function fn4(arr: Array<number>[]) { return arr; }
672686
· ─────────────
673687
╰────
674688
help: Replace `Array<number>` with `number[]`.
689+
690+
⚠ typescript-eslint(array-type): Array type using 'T[]' is forbidden for non-simple types. Use 'Array<T>' instead.
691+
╭─[array_type.ts:2:29]
692+
1 │ function testFn<T>(param: T) { return param; }
693+
2 │ export const test2 = testFn<{name: string}[]>([]);
694+
· ────────────────
695+
╰────
696+
help: Replace `{name: string}[]` with `Array<{name: string}>`.
697+
698+
⚠ typescript-eslint(array-type): Array type using 'Array<T>' is forbidden. Use 'T[]' instead.
699+
╭─[array_type.ts:2:29]
700+
1 │ function testFn<T>(param: T) { return param; }
701+
2 │ export const test2 = testFn<Array<{name: string}>>([]);
702+
· ─────────────────────
703+
╰────
704+
help: Replace `Array<{name: string}>` with `{name: string}[]`.
705+
706+
⚠ typescript-eslint(array-type): Array type using 'string[]' is forbidden. Use 'Array<string>' instead.
707+
╭─[array_type.ts:2:29]
708+
1 │ function testFn<T>(param: T) { return param; }
709+
2 │ export const test2 = testFn<string[]>([]);
710+
· ────────
711+
╰────
712+
help: Replace `string[]` with `Array<string>`.
713+
714+
⚠ typescript-eslint(array-type): Array type using 'T[]' is forbidden. Use 'Array<T>' instead.
715+
╭─[array_type.ts:2:29]
716+
1 │ function testFn<T>(param: T) { return param; }
717+
2 │ export const test2 = testFn<(string | number)[]>([]);
718+
· ───────────────────
719+
╰────
720+
help: Replace `(string | number)[]` with `Array<string | number>`.
721+
722+
⚠ typescript-eslint(array-type): Array type using 'readonly string[]' is forbidden. Use 'ReadonlyArray<string>' instead.
723+
╭─[array_type.ts:2:29]
724+
1 │ function testFn<T>(param: T) { return param; }
725+
2 │ export const test2 = testFn<readonly string[]>([]);
726+
· ─────────────────
727+
╰────
728+
help: Replace `readonly string[]` with `ReadonlyArray<string>`.
729+
730+
⚠ typescript-eslint(array-type): Array type using 'ReadonlyArray<string>' is forbidden. Use 'readonly string[]' instead.
731+
╭─[array_type.ts:2:29]
732+
1 │ function testFn<T>(param: T) { return param; }
733+
2 │ export const test2 = testFn<ReadonlyArray<string>>([]);
734+
· ─────────────────────
735+
╰────
736+
help: Replace `ReadonlyArray<string>` with `readonly string[]`.

0 commit comments

Comments
 (0)