mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(linter): catch Promise in typescript/array-type rule (#8702)
close #8693 Correctly catch `Promise<string[]>` and `Promise<Array<number>>`.
This commit is contained in:
parent
e8e69179d1
commit
f15bdce53b
2 changed files with 76 additions and 6 deletions
|
|
@ -176,7 +176,7 @@ fn check(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let TSType::TSTypeReference(ts_type_reference) = &type_annotation {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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(
|
fn check_and_report_error_array(
|
||||||
default_config: &ArrayOption,
|
default_config: &ArrayOption,
|
||||||
readonly_config: &ArrayOption,
|
readonly_config: &ArrayOption,
|
||||||
|
|
@ -248,11 +307,6 @@ fn check_and_report_error_array(
|
||||||
return;
|
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 is_readonly_array_type = ident_ref_type_name.name == "ReadonlyArray";
|
||||||
let config = if is_readonly_array_type { readonly_config } else { default_config };
|
let config = if is_readonly_array_type { readonly_config } else { default_config };
|
||||||
if matches!(config, ArrayOption::Generic) {
|
if matches!(config, ArrayOption::Generic) {
|
||||||
|
|
@ -1116,6 +1170,10 @@ fn test() {
|
||||||
"const foo: ReadonlyArray<new (...args: any[]) => void> = [];",
|
"const foo: ReadonlyArray<new (...args: any[]) => void> = [];",
|
||||||
Some(serde_json::json!([{"default":"array"}])),
|
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![
|
let fix: Vec<(&str, &str, Option<serde_json::Value>)> = vec![
|
||||||
|
|
@ -1643,6 +1701,11 @@ fn test() {
|
||||||
"const foo: readonly (new (...args: any[]) => void)[] = [];",
|
"const foo: readonly (new (...args: any[]) => void)[] = [];",
|
||||||
Some(serde_json::json!([{"default":"array"}])),
|
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();
|
Tester::new(ArrayType::NAME, ArrayType::PLUGIN, pass, fail).expect_fix(fix).test_and_snapshot();
|
||||||
|
|
|
||||||
|
|
@ -652,3 +652,10 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
· ───────────────────────────────────────────
|
· ───────────────────────────────────────────
|
||||||
╰────
|
╰────
|
||||||
help: Replace `ReadonlyArray<new (...args: any[]) => void>` with `readonly (new (...args: any[]) => void)[]`.
|
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>`.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue