diff --git a/crates/biome_js_analyze/src/lint/nursery/use_explicit_type.rs b/crates/biome_js_analyze/src/lint/nursery/use_explicit_type.rs index dd4bda33b777..94d29142c5b0 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_explicit_type.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_explicit_type.rs @@ -246,6 +246,10 @@ impl Rule for UseExplicitType { return None; } + if is_arrow_func(func) && is_function_used_in_object(func) { + return None; + } + if is_higher_order_function(func) { return None; } @@ -362,6 +366,38 @@ fn is_function_used_in_argument_or_array(func: &AnyJsFunction) -> bool { ) } +/// Check if the function is used in some object +/// +/// # Examples +/// +/// JS_OBJECT: +/// +/// interface Behavior { +/// attribute: string; +/// func: () => string; +/// arrowFunc: () => string; +/// } +/// +/// function getObjectWithFunction(): Behavior { +/// return { +/// attribute: 'value', +/// func: function myFunc(): string { return "value" }, +/// arrowFunc: () => {}, +/// } +/// } +/// +fn is_function_used_in_object(func: &AnyJsFunction) -> bool { + matches!( + func.syntax().parent().kind(), + Some(JsSyntaxKind::JS_PROPERTY_OBJECT_MEMBER) + ) +} + +/// Check if a function is an arrow function +fn is_arrow_func(func: &AnyJsFunction) -> bool { + func.as_js_arrow_function_expression().is_some() +} + /// Checks if a function is an IIFE (Immediately Invoked Function Expressions) /// /// # Examples diff --git a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts index 1cb6ba5f394e..42887f442195 100644 --- a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts +++ b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts @@ -91,5 +91,20 @@ function fn() { }; } -const x = { prop: () => {} } -const x = { bar: { prop: () => {} } } \ No newline at end of file +const x = { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } +const x = { bar: { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } } + + +// Returning object from function +interface Behavior { + attribute: string; + namedFunc: () => string; + arrowFunc: () => string; +} + +function getObjectWithFunction(): Behavior { + return { + namedFunc: function myFunc() { return "value" }, + arrowFunc: () => {}, + } +} diff --git a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts.snap b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts.snap index 6f34976d42c3..c81b2709cd5a 100644 --- a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts.snap +++ b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/invalid.ts.snap @@ -1,5 +1,6 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 86 expression: invalid.ts --- # Input @@ -97,8 +98,24 @@ function fn() { }; } -const x = { prop: () => {} } -const x = { bar: { prop: () => {} } } +const x = { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } +const x = { bar: { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } } + + +// Returning object from function +interface Behavior { + attribute: string; + namedFunc: () => string; + arrowFunc: () => string; +} + +function getObjectWithFunction(): Behavior { + return { + namedFunc: function myFunc() { return "value" }, + arrowFunc: () => {}, + } +} + ``` # Diagnostics @@ -532,15 +549,69 @@ invalid.ts:85:2 lint/nursery/useExplicitType ━━━━━━━━━━━ ``` ``` -invalid.ts:94:19 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:94:29 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Missing return type on function. 92 │ } 93 │ - > 94 │ const x = { prop: () => {} } - │ ^^^^^^^^^ - 95 │ const x = { bar: { prop: () => {} } } + > 94 │ const x = { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } + │ ^^^^^^^^^^^^^^^ + 95 │ const x = { bar: { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } } + 96 │ + + i Declaring the return type makes the code self-documenting and can speed up TypeScript type checking. + + i Add a return type annotation. + + +``` + +``` +invalid.ts:94:81 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Missing return type on function. + + 92 │ } + 93 │ + > 94 │ const x = { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } + │ ^^^^^^^^^ + 95 │ const x = { bar: { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } } + 96 │ + + i Declaring the return type makes the code self-documenting and can speed up TypeScript type checking. + + i Add a return type annotation. + + +``` + +``` +invalid.ts:95:36 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Missing return type on function. + + 94 │ const x = { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } + > 95 │ const x = { bar: { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } } + │ ^^^^^^^^^^^^^^^ + 96 │ + + i Declaring the return type makes the code self-documenting and can speed up TypeScript type checking. + + i Add a return type annotation. + + +``` + +``` +invalid.ts:95:79 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Missing return type on function. + + 94 │ const x = { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } + > 95 │ const x = { bar: { namedFunctions: function alpha () => {}, unNamedFunctions: function () => {} } } + │ ^^^^^^^^^^^^ + 96 │ i Declaring the return type makes the code self-documenting and can speed up TypeScript type checking. @@ -550,13 +621,16 @@ invalid.ts:94:19 lint/nursery/useExplicitType ━━━━━━━━━━━ ``` ``` -invalid.ts:95:26 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:107:16 lint/nursery/useExplicitType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Missing return type on function. - 94 │ const x = { prop: () => {} } - > 95 │ const x = { bar: { prop: () => {} } } - │ ^^^^^^^^^ + 105 │ function getObjectWithFunction(): Behavior { + 106 │ return { + > 107 │ namedFunc: function myFunc() { return "value" }, + │ ^^^^^^^^^^^^^^^ + 108 │ arrowFunc: () => {}, + 109 │ } i Declaring the return type makes the code self-documenting and can speed up TypeScript type checking. diff --git a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts index 41f4283c04c6..dc49ee64fbde 100644 --- a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts +++ b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts @@ -102,4 +102,17 @@ class Accumulator { this.count += fn(); } } -new Accumulator().accumulate(() => 1); \ No newline at end of file +new Accumulator().accumulate(() => 1); + +// Returning object from function +interface Behavior { + namedFunc: () => string; + arrowFunc: () => string; +} + +function getObjectWithFunction(): Behavior { + return { + namedFunc: function myFunc(): string { return "value" }, + arrowFunc: () => {}, + } +} diff --git a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts.snap b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts.snap index 45a4d83905d7..e145cc18edbc 100644 --- a/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts.snap +++ b/crates/biome_js_analyze/tests/specs/nursery/useExplicitType/valid.ts.snap @@ -1,5 +1,6 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 86 expression: valid.ts --- # Input @@ -109,4 +110,18 @@ class Accumulator { } } new Accumulator().accumulate(() => 1); + +// Returning object from function +interface Behavior { + namedFunc: () => string; + arrowFunc: () => string; +} + +function getObjectWithFunction(): Behavior { + return { + namedFunc: function myFunc(): string { return "value" }, + arrowFunc: () => {}, + } +} + ```