Skip to content

Commit e8dbc56

Browse files
committed
fix(linter/array-type): enable edge case tests (#22047)
Fixes array-type autofixes for restored edge case coverage around qualified types, type assertions, infer types, aliases, and nested readonly arrays.
1 parent d57b51f commit e8dbc56

2 files changed

Lines changed: 194 additions & 63 deletions

File tree

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

Lines changed: 114 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ impl Rule for ArrayType {
228228
return;
229229
}
230230
check_and_report_error_reference(
231+
node,
231232
self.default_config(),
232233
&readonly_config,
233234
ts_type_reference,
@@ -279,7 +280,7 @@ fn type_needs_parentheses(type_param: &TSType) -> bool {
279280
if let TSTypeName::IdentifierReference(identifier_reference) = &node.type_name {
280281
return identifier_reference.name.as_str() == "ReadonlyArray";
281282
}
282-
true
283+
false
283284
}
284285
TSType::TSUnionType(_)
285286
| TSType::TSFunctionType(_)
@@ -332,6 +333,7 @@ fn check_and_report_error_generic(
332333
}
333334

334335
fn check_and_report_error_reference(
336+
node: &AstNode,
335337
default_config: &ArrayOption,
336338
readonly_config: &ArrayOption,
337339
ts_type_reference: &TSTypeReference,
@@ -341,7 +343,7 @@ fn check_and_report_error_reference(
341343
&& (ident_ref_type_name.name.as_str() == "ReadonlyArray"
342344
|| ident_ref_type_name.name.as_str() == "Array")
343345
{
344-
check_and_report_error_array(default_config, readonly_config, ts_type_reference, ctx);
346+
check_and_report_error_array(node, default_config, readonly_config, ts_type_reference, ctx);
345347
}
346348
}
347349

@@ -407,6 +409,7 @@ fn array_type_would_report<'a>(
407409
}
408410

409411
fn check_and_report_error_array(
412+
node: &AstNode,
410413
default_config: &ArrayOption,
411414
readonly_config: &ArrayOption,
412415
ts_type_reference: &TSTypeReference,
@@ -450,14 +453,8 @@ fn check_and_report_error_array(
450453
}
451454

452455
let type_parens = type_needs_parentheses(first_type_param);
453-
// TODO: support example: type Foo = ReadonlyArray<object>[]; -> type Foo = (readonly object[])[];
454-
// let mut parent_parens: bool = readonly_prefix != "";
455-
// if let Some(parent) = ctx.nodes().parent_node(node.id()) {
456-
// if let AstKind::TSTypeAnnotation(parent_node) = parent.kind() {}
457-
// } else {
458-
// parent_parens = false
459-
// };
460-
let parent_parens = false;
456+
let parent_parens = is_readonly_array_type
457+
&& matches!(ctx.nodes().parent_kind(node.id()), AstKind::TSArrayType(_));
461458

462459
let element_type_span = get_ts_element_type_span(first_type_param);
463460
let Some(element_type_span) = element_type_span else {
@@ -1196,7 +1193,10 @@ const instance = new MyClass<number>(42);",
11961193
),
11971194
("let a: { foo: Array<Bar> }[] = [];", Some(serde_json::json!([{"default":"array"}]))),
11981195
("let a: Array<{ foo: Bar[] }> = [];", Some(serde_json::json!([{"default":"generic"}]))),
1199-
// ("let a: Array<{ foo: Foo | Bar[] }> = [];", Some(serde_json::json!([{"default":"generic"}]))),
1196+
(
1197+
"let a: Array<{ foo: Foo | Bar[] }> = [];",
1198+
Some(serde_json::json!([{"default":"generic"}])),
1199+
),
12001200
(
12011201
"function foo(a: Array<Bar>): Array<Bar> {}",
12021202
Some(serde_json::json!([{"default":"array"}])),
@@ -1205,20 +1205,21 @@ const instance = new MyClass<number>(42);",
12051205
"let x: Array<undefined> = [undefined] as undefined[];",
12061206
Some(serde_json::json!([{"default":"array-simple"}])),
12071207
),
1208-
// (
1209-
// "let y: string[] = <Array<string>>['2'];",
1210-
// Some(serde_json::json!([{"default":"array-simple"}])),
1211-
// ),
1208+
(
1209+
"let y: string[] = <Array<string>>['2'];",
1210+
Some(serde_json::json!([{"default":"array-simple"}])),
1211+
),
12121212
("let z: Array = [3, '4'];", Some(serde_json::json!([{"default":"array-simple"}]))),
12131213
(
12141214
"let ya = [[1, '2']] as [number, string][];",
12151215
Some(serde_json::json!([{"default":"array-simple"}])),
12161216
),
12171217
("type Arr<T> = Array<T>;", Some(serde_json::json!([{"default":"array-simple"}]))),
1218-
// ("
1219-
// // Ignore user defined aliases
1220-
// let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];
1221-
// ", Some(serde_json::json!([{"default":"array-simple"}]))),
1218+
(
1219+
"// Ignore user defined aliases
1220+
let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];",
1221+
Some(serde_json::json!([{"default":"array-simple"}])),
1222+
),
12221223
(
12231224
"
12241225
interface ArrayClass<T> {
@@ -1250,19 +1251,26 @@ const instance = new MyClass<number>(42);",
12501251
"type barIntersection = (string & number)[];",
12511252
Some(serde_json::json!([{"default":"array-simple"}])),
12521253
),
1253-
// ("let v: Array<fooName.BarType> = [{ bar: 'bar' }];", Some(serde_json::json!([{"default":"array-simple"}]))),
1254-
// ("let w: fooName.BazType<string>[] = [['baz']];", Some(serde_json::json!([{"default":"array-simple"}]))),
1254+
(
1255+
"let v: Array<fooName.BarType> = [{ bar: 'bar' }];",
1256+
Some(serde_json::json!([{"default":"array-simple"}])),
1257+
),
1258+
(
1259+
"let w: fooName.BazType<string>[] = [['baz']];",
1260+
Some(serde_json::json!([{"default":"array-simple"}])),
1261+
),
12551262
(
12561263
"let x: Array<undefined> = [undefined] as undefined[];",
12571264
Some(serde_json::json!([{"default":"array"}])),
12581265
),
1259-
// ("let y: string[] = <Array<string>>['2'];", Some(serde_json::json!([{"default":"array"}]))),
1266+
("let y: string[] = <Array<string>>['2'];", Some(serde_json::json!([{"default":"array"}]))),
12601267
("let z: Array = [3, '4'];", Some(serde_json::json!([{"default":"array"}]))),
12611268
("type Arr<T> = Array<T>;", Some(serde_json::json!([{"default":"array"}]))),
1262-
// ("
1263-
// // Ignore user defined aliases
1264-
// let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];
1265-
// ", Some(serde_json::json!([{"default":"array"}]))),
1269+
(
1270+
"// Ignore user defined aliases
1271+
let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];",
1272+
Some(serde_json::json!([{"default":"array"}])),
1273+
),
12661274
(
12671275
"
12681276
interface ArrayClass<T> {
@@ -1305,10 +1313,11 @@ const instance = new MyClass<number>(42);",
13051313
"let ya = [[1, '2']] as [number, string][];",
13061314
Some(serde_json::json!([{"default":"generic"}])),
13071315
),
1308-
// ("
1309-
// // Ignore user defined aliases
1310-
// let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];
1311-
// ", Some(serde_json::json!([{"default":"generic"}]))),
1316+
(
1317+
"// Ignore user defined aliases
1318+
let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];",
1319+
Some(serde_json::json!([{"default":"generic"}])),
1320+
),
13121321
(
13131322
"
13141323
interface ArrayClass<T> {
@@ -1347,9 +1356,15 @@ const instance = new MyClass<number>(42);",
13471356
",
13481357
Some(serde_json::json!([{"default":"generic"}])),
13491358
),
1350-
// ("type Unwrap<T> = T extends Array<infer E> ? E : T;", Some(serde_json::json!([{"default":"array"}]))),
1351-
// ("type Unwrap<T> = T extends (infer E)[] ? E : T;", Some(serde_json::json!([{"default":"generic"}]))),
1352-
// ("type Foo = ReadonlyArray<object>[];", Some(serde_json::json!([{"default":"array"}]))),
1359+
(
1360+
"type Unwrap<T> = T extends Array<infer E> ? E : T;",
1361+
Some(serde_json::json!([{"default":"array"}])),
1362+
),
1363+
(
1364+
"type Unwrap<T> = T extends (infer E)[] ? E : T;",
1365+
Some(serde_json::json!([{"default":"generic"}])),
1366+
),
1367+
("type Foo = ReadonlyArray<object>[];", Some(serde_json::json!([{"default":"array"}]))),
13531368
(
13541369
"const foo: Array<new (...args: any[]) => void> = [];",
13551370
Some(serde_json::json!([{"default":"array"}])),
@@ -1804,7 +1819,11 @@ export const test8 = testFn<Array<string>, number[]>([]);",
18041819
"let a: Array<{ foo: Array<Bar> }> = [];",
18051820
Some(serde_json::json!([{"default":"generic"}])),
18061821
),
1807-
// ("let a: Array<{ foo: Foo | Bar[] }> = [];", "let a: Array<{ foo: Foo | Array<Bar> }> = [];", Some(serde_json::json!([{"default":"generic"}]))),
1822+
(
1823+
"let a: Array<{ foo: Foo | Bar[] }> = [];",
1824+
"let a: Array<{ foo: Foo | Array<Bar> }> = [];",
1825+
Some(serde_json::json!([{"default":"generic"}])),
1826+
),
18081827
(
18091828
"function foo(a: Array<Bar>): Array<Bar> {}",
18101829
"function foo(a: Bar[]): Bar[] {}",
@@ -1815,7 +1834,11 @@ export const test8 = testFn<Array<string>, number[]>([]);",
18151834
"let x: undefined[] = [undefined] as undefined[];",
18161835
Some(serde_json::json!([{"default":"array-simple"}])),
18171836
),
1818-
// ("let y: string[] = <Array<string>>['2'];", "let y: string[] = <string[]>['2'];", Some(serde_json::json!([{"default":"array-simple"}]))),
1837+
(
1838+
"let y: string[] = <Array<string>>['2'];",
1839+
"let y: string[] = <string[]>['2'];",
1840+
Some(serde_json::json!([{"default":"array-simple"}])),
1841+
),
18191842
(
18201843
"let z: Array = [3, '4'];",
18211844
"let z: any[] = [3, '4'];",
@@ -1831,13 +1854,13 @@ export const test8 = testFn<Array<string>, number[]>([]);",
18311854
"type Arr<T> = T[];",
18321855
Some(serde_json::json!([{"default":"array-simple"}])),
18331856
),
1834-
// ("
1835-
// // Ignore user defined aliases
1836-
// let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];
1837-
// ", "
1838-
// // Ignore user defined aliases
1839-
// let yyyy: Arr<Array<Array<Arr<string>>>> = [[[['2']]]];
1840-
// ", Some(serde_json::json!([{"default":"array-simple"}]))),
1857+
(
1858+
"// Ignore user defined aliases
1859+
let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];",
1860+
"// Ignore user defined aliases
1861+
let yyyy: Arr<Array<Array<Arr<string>>>> = [[[['2']]]];",
1862+
Some(serde_json::json!([{"default":"array-simple"}])),
1863+
),
18411864
(
18421865
"
18431866
interface ArrayClass<T> {
@@ -1885,14 +1908,26 @@ export const test8 = testFn<Array<string>, number[]>([]);",
18851908
"type barIntersection = Array<string & number>;",
18861909
Some(serde_json::json!([{"default":"array-simple"}])),
18871910
),
1888-
// ("let v: Array<fooName.BarType> = [{ bar: 'bar' }];", "let v: fooName.BarType[] = [{ bar: 'bar' }];", Some(serde_json::json!([{"default":"array-simple"}]))),
1889-
// ("let w: fooName.BazType<string>[] = [['baz']];", "let w: Array<fooName.BazType<string>> = [['baz']];", Some(serde_json::json!([{"default":"array-simple"}]))),
1911+
(
1912+
"let v: Array<fooName.BarType> = [{ bar: 'bar' }];",
1913+
"let v: fooName.BarType[] = [{ bar: 'bar' }];",
1914+
Some(serde_json::json!([{"default":"array-simple"}])),
1915+
),
1916+
(
1917+
"let w: fooName.BazType<string>[] = [['baz']];",
1918+
"let w: Array<fooName.BazType<string>> = [['baz']];",
1919+
Some(serde_json::json!([{"default":"array-simple"}])),
1920+
),
18901921
(
18911922
"let x: Array<undefined> = [undefined] as undefined[];",
18921923
"let x: undefined[] = [undefined] as undefined[];",
18931924
Some(serde_json::json!([{"default":"array"}])),
18941925
),
1895-
// ("let y: string[] = <Array<string>>['2'];", "let y: string[] = <string[]>['2'];", Some(serde_json::json!([{"default":"array"}]))),
1926+
(
1927+
"let y: string[] = <Array<string>>['2'];",
1928+
"let y: string[] = <string[]>['2'];",
1929+
Some(serde_json::json!([{"default":"array"}])),
1930+
),
18961931
(
18971932
"let z: Array = [3, '4'];",
18981933
"let z: any[] = [3, '4'];",
@@ -1903,13 +1938,13 @@ export const test8 = testFn<Array<string>, number[]>([]);",
19031938
"type Arr<T> = T[];",
19041939
Some(serde_json::json!([{"default":"array"}])),
19051940
),
1906-
// ("
1907-
// // Ignore user defined aliases
1908-
// let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];
1909-
// ", "
1910-
// // Ignore user defined aliases
1911-
// let yyyy: Arr<Arr<string>[][]> = [[[['2']]]];
1912-
// ", Some(serde_json::json!([{"default":"array"}]))),
1941+
(
1942+
"// Ignore user defined aliases
1943+
let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];",
1944+
"// Ignore user defined aliases
1945+
let yyyy: Arr<Arr<string>[][]> = [[[['2']]]];",
1946+
Some(serde_json::json!([{"default":"array"}])),
1947+
),
19131948
(
19141949
"
19151950
interface ArrayClass<T> {
@@ -1960,19 +1995,23 @@ export const test8 = testFn<Array<string>, number[]>([]);",
19601995
"let x: Array<number> = [1] as Array<number>;",
19611996
Some(serde_json::json!([{"default":"generic"}])),
19621997
),
1963-
// ("let y: string[] = <Array<string>>['2'];", "let y: Array<string> = <Array<string>>['2'];", Some(serde_json::json!([{"default":"generic"}]))),
1998+
(
1999+
"let y: string[] = <Array<string>>['2'];",
2000+
"let y: Array<string> = <Array<string>>['2'];",
2001+
Some(serde_json::json!([{"default":"generic"}])),
2002+
),
19642003
(
19652004
"let ya = [[1, '2']] as [number, string][];",
19662005
"let ya = [[1, '2']] as Array<[number, string]>;",
19672006
Some(serde_json::json!([{"default":"generic"}])),
19682007
),
1969-
// ("
1970-
// // Ignore user defined aliases
1971-
// let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];
1972-
// ", "
1973-
// // Ignore user defined aliases
1974-
// let yyyy: Arr<Array<Array<Arr<string>>>> = [[[['2']]]];
1975-
// ", Some(serde_json::json!([{"default":"generic"}]))),
2008+
(
2009+
"// Ignore user defined aliases
2010+
let yyyy: Arr<Array<Arr<string>>[]> = [[[['2']]]];",
2011+
"// Ignore user defined aliases
2012+
let yyyy: Arr<Array<Array<Arr<string>>>> = [[[['2']]]];",
2013+
Some(serde_json::json!([{"default":"generic"}])),
2014+
),
19762015
(
19772016
"
19782017
interface ArrayClass<T> {
@@ -2031,9 +2070,21 @@ export const test8 = testFn<Array<string>, number[]>([]);",
20312070
",
20322071
Some(serde_json::json!([{"default":"generic"}])),
20332072
),
2034-
// ("type Unwrap<T> = T extends Array<infer E> ? E : T;", "type Unwrap<T> = T extends (infer E)[] ? E : T;", Some(serde_json::json!([{"default":"array"}]))),
2035-
// ("type Unwrap<T> = T extends (infer E)[] ? E : T;", "type Unwrap<T> = T extends Array<infer E> ? E : T;", Some(serde_json::json!([{"default":"generic"}]))),
2036-
// ("type Foo = ReadonlyArray<object>[];", "type Foo = (readonly object[])[];", Some(serde_json::json!([{"default":"array"}]))),
2073+
(
2074+
"type Unwrap<T> = T extends Array<infer E> ? E : T;",
2075+
"type Unwrap<T> = T extends (infer E)[] ? E : T;",
2076+
Some(serde_json::json!([{"default":"array"}])),
2077+
),
2078+
(
2079+
"type Unwrap<T> = T extends (infer E)[] ? E : T;",
2080+
"type Unwrap<T> = T extends Array<infer E> ? E : T;",
2081+
Some(serde_json::json!([{"default":"generic"}])),
2082+
),
2083+
(
2084+
"type Foo = ReadonlyArray<object>[];",
2085+
"type Foo = (readonly object[])[];",
2086+
Some(serde_json::json!([{"default":"array"}])),
2087+
),
20372088
(
20382089
"const foo: Array<new (...args: any[]) => void> = [];",
20392090
"const foo: (new (...args: any[]) => void)[] = [];",

0 commit comments

Comments
 (0)