Skip to content
29 changes: 17 additions & 12 deletions packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,12 @@ function doesImmediatelyReturnFunctionExpression({
/**
* Checks if a function belongs to:
* ```
* () => ({ action: 'xxx' } as const)
* ({ action: 'xxx' } as const)
* ```
*/
function returnsConstAssertionDirectly(
node: TSESTree.ArrowFunctionExpression,
): boolean {
const { body } = node;
if (isTypeAssertion(body)) {
const { typeAnnotation } = body;
function isConstAssertion(node: TSESTree.Node): boolean {
if (isTypeAssertion(node)) {
const { typeAnnotation } = node;
if (typeAnnotation.type === AST_NODE_TYPES.TSTypeReference) {
const { typeName } = typeAnnotation;
if (
Expand Down Expand Up @@ -256,11 +253,19 @@ function isValidFunctionExpressionReturnType(
}

// https://github.com/typescript-eslint/typescript-eslint/issues/653
return (
options.allowDirectConstAssertionInArrowFunctions === true &&
node.type === AST_NODE_TYPES.ArrowFunctionExpression &&
returnsConstAssertionDirectly(node)
);
if (
!options.allowDirectConstAssertionInArrowFunctions ||
node.type !== AST_NODE_TYPES.ArrowFunctionExpression
) {
return false;
}

let body = node.body;
while (body.type === AST_NODE_TYPES.TSSatisfiesExpression) {
body = body.expression;
}

return isConstAssertion(body);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,53 @@ const func = (value: number) => x as const;
},
{
code: `
interface R {
type: string;
value: number;
}

const func = (value: number) => ({ type: 'X', value }) as const satisfies R;
`,
options: [
{
allowDirectConstAssertionInArrowFunctions: true,
},
],
},
{
code: `
interface R {
type: string;
value: number;
}

const func = (value: number) =>
({ type: 'X', value }) as const satisfies R satisfies R;
`,
options: [
{
allowDirectConstAssertionInArrowFunctions: true,
},
],
},
{
code: `
interface R {
type: string;
value: number;
}

const func = (value: number) =>
({ type: 'X', value }) as const satisfies R satisfies R satisfies R;
`,
options: [
{
allowDirectConstAssertionInArrowFunctions: true,
},
],
},
{
code: `
new Promise(resolve => {});
new Foo(1, () => {});
`,
Expand Down Expand Up @@ -1731,6 +1778,30 @@ const func = (value: number) => ({ type: 'X', value }) as const;
},
],
},
{
code: `
interface R {
type: string;
value: number;
}

const func = (value: number) => ({ type: 'X', value }) as const satisfies R;
`,
errors: [
{
column: 30,
endColumn: 32,
endLine: 7,
line: 7,
messageId: 'missingReturnType',
},
],
options: [
{
allowDirectConstAssertionInArrowFunctions: false,
},
],
},
{
code: 'const log = (message: string) => void console.log(message);',
errors: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,54 @@ export const func4 = (value: number) => x as const;
},
{
code: `
interface R {
type: string;
value: number;
}

export const func = (value: number) =>
({ type: 'X', value }) as const satisfies R;
`,
options: [
{
allowDirectConstAssertionInArrowFunctions: true,
},
],
},
{
code: `
interface R {
type: string;
value: number;
}

export const func = (value: number) =>
({ type: 'X', value }) as const satisfies R satisfies R;
`,
options: [
{
allowDirectConstAssertionInArrowFunctions: true,
},
],
},
{
code: `
interface R {
type: string;
value: number;
}

export const func = (value: number) =>
({ type: 'X', value }) as const satisfies R satisfies R satisfies R;
`,
options: [
{
allowDirectConstAssertionInArrowFunctions: true,
},
],
},
{
code: `
export const func1 = (value: string) => value;
export const func2 = (value: number) => ({ type: 'X', value });
`,
Expand Down Expand Up @@ -1204,6 +1252,31 @@ export const func = (value: number) => ({ type: 'X', value }) as const;
},
{
code: `
interface R {
type: string;
value: number;
}

export const func = (value: number) =>
({ type: 'X', value }) as const satisfies R;
`,
errors: [
{
column: 37,
endColumn: 39,
endLine: 7,
line: 7,
messageId: 'missingReturnType',
},
],
options: [
{
allowDirectConstAssertionInArrowFunctions: false,
},
],
},
{
code: `
export class Test {
constructor() {}
get prop() {
Expand Down
Loading