Skip to content

Commit

Permalink
fix(linter): catch Promise in typescript/array-type rule (#8702)
Browse files Browse the repository at this point in the history
close #8693 

Correctly catch `Promise<string[]>` and `Promise<Array<number>>`.
  • Loading branch information
re-taro authored Jan 25, 2025
1 parent e8e6917 commit f15bdce
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 6 deletions.
75 changes: 69 additions & 6 deletions crates/oxc_linter/src/rules/typescript/array_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ fn check(
}

if let TSType::TSTypeReference(ts_type_reference) = &type_annotation {
check_and_report_error_array(default_config, readonly_config, ts_type_reference, ctx);
check_and_report_error_reference(default_config, readonly_config, ts_type_reference, ctx);
}
}

Expand Down Expand Up @@ -238,6 +238,65 @@ fn check_and_report_error_generic(
});
}

fn check_and_report_error_reference(
default_config: &ArrayOption,
readonly_config: &ArrayOption,
ts_type_reference: &TSTypeReference,
ctx: &LintContext,
) {
if let TSTypeName::IdentifierReference(ident_ref_type_name) = &ts_type_reference.type_name {
if ident_ref_type_name.name.as_str() == "ReadonlyArray"
|| ident_ref_type_name.name.as_str() == "Array"
{
check_and_report_error_array(default_config, readonly_config, ts_type_reference, ctx);
} else if ident_ref_type_name.name.as_str() == "Promise" {
if let Some(type_params) = &ts_type_reference.type_parameters {
if type_params.params.len() == 1 {
if let Some(type_param) = type_params.params.first() {
if let TSType::TSArrayType(array_type) = &type_param {
check_and_report_error_generic(
default_config,
array_type.span,
&array_type.element_type,
ctx,
false,
);
}

if let TSType::TSTypeOperatorType(ts_operator_type) = &type_param {
if matches!(
&ts_operator_type.operator,
TSTypeOperatorOperator::Readonly
) {
if let TSType::TSArrayType(array_type) =
&ts_operator_type.type_annotation
{
check_and_report_error_generic(
readonly_config,
ts_operator_type.span,
&array_type.element_type,
ctx,
true,
);
}
}
}

if let TSType::TSTypeReference(ts_type_reference) = &type_param {
check_and_report_error_reference(
default_config,
readonly_config,
ts_type_reference,
ctx,
);
}
}
}
}
}
}
}

fn check_and_report_error_array(
default_config: &ArrayOption,
readonly_config: &ArrayOption,
Expand All @@ -248,11 +307,6 @@ fn check_and_report_error_array(
return;
};

if ident_ref_type_name.name.as_str() != "ReadonlyArray"
&& ident_ref_type_name.name.as_str() != "Array"
{
return;
}
let is_readonly_array_type = ident_ref_type_name.name == "ReadonlyArray";
let config = if is_readonly_array_type { readonly_config } else { default_config };
if matches!(config, ArrayOption::Generic) {
Expand Down Expand Up @@ -1116,6 +1170,10 @@ fn test() {
"const foo: ReadonlyArray<new (...args: any[]) => void> = [];",
Some(serde_json::json!([{"default":"array"}])),
),
(
"let a: Promise<string[]> = Promise.resolve([]);",
Some(serde_json::json!([{"default": "generic"}])),
),
];

let fix: Vec<(&str, &str, Option<serde_json::Value>)> = vec![
Expand Down Expand Up @@ -1643,6 +1701,11 @@ fn test() {
"const foo: readonly (new (...args: any[]) => void)[] = [];",
Some(serde_json::json!([{"default":"array"}])),
),
(
"let a: Promise<string[]> = Promise.resolve([]);",
"let a: Promise<Array<string>> = Promise.resolve([]);",
Some(serde_json::json!([{"default": "generic"}])),
),
];

Tester::new(ArrayType::NAME, ArrayType::PLUGIN, pass, fail).expect_fix(fix).test_and_snapshot();
Expand Down
7 changes: 7 additions & 0 deletions crates/oxc_linter/src/snapshots/typescript_array_type.snap
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,10 @@ source: crates/oxc_linter/src/tester.rs
· ───────────────────────────────────────────
╰────
help: Replace `ReadonlyArray<new (...args: any[]) => void>` with `readonly (new (...args: any[]) => void)[]`.

⚠ typescript-eslint(array-type): Array type using 'string[]' is forbidden. Use 'Array<string>' instead.
╭─[array_type.tsx:1:16]
1 │ let a: Promise<string[]> = Promise.resolve([]);
· ────────
╰────
help: Replace `string[]` with `Array<string>`.

0 comments on commit f15bdce

Please sign in to comment.