diff --git a/crates/oxc_linter/src/rules/typescript/array_type.rs b/crates/oxc_linter/src/rules/typescript/array_type.rs index 5e3c67f0d..51acd552e 100644 --- a/crates/oxc_linter/src/rules/typescript/array_type.rs +++ b/crates/oxc_linter/src/rules/typescript/array_type.rs @@ -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); } } @@ -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, @@ -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) { @@ -1116,6 +1170,10 @@ fn test() { "const foo: ReadonlyArray void> = [];", Some(serde_json::json!([{"default":"array"}])), ), + ( + "let a: Promise = Promise.resolve([]);", + Some(serde_json::json!([{"default": "generic"}])), + ), ]; let fix: Vec<(&str, &str, Option)> = vec![ @@ -1643,6 +1701,11 @@ fn test() { "const foo: readonly (new (...args: any[]) => void)[] = [];", Some(serde_json::json!([{"default":"array"}])), ), + ( + "let a: Promise = Promise.resolve([]);", + "let a: Promise> = Promise.resolve([]);", + Some(serde_json::json!([{"default": "generic"}])), + ), ]; Tester::new(ArrayType::NAME, ArrayType::PLUGIN, pass, fail).expect_fix(fix).test_and_snapshot(); diff --git a/crates/oxc_linter/src/snapshots/typescript_array_type.snap b/crates/oxc_linter/src/snapshots/typescript_array_type.snap index 13be26fb6..d99f987a4 100644 --- a/crates/oxc_linter/src/snapshots/typescript_array_type.snap +++ b/crates/oxc_linter/src/snapshots/typescript_array_type.snap @@ -652,3 +652,10 @@ source: crates/oxc_linter/src/tester.rs · ─────────────────────────────────────────── ╰──── help: Replace `ReadonlyArray void>` with `readonly (new (...args: any[]) => void)[]`. + + ⚠ typescript-eslint(array-type): Array type using 'string[]' is forbidden. Use 'Array' instead. + ╭─[array_type.tsx:1:16] + 1 │ let a: Promise = Promise.resolve([]); + · ──────── + ╰──── + help: Replace `string[]` with `Array`.