Skip to content

Commit

Permalink
feat(eslint-plugin): [prefer-reduce-type-parameter] supports tuple, u…
Browse files Browse the repository at this point in the history
…nion, intersection
  • Loading branch information
yeonjuan committed Mar 11, 2024
1 parent 3fef9d6 commit a61eecc
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
14 changes: 13 additions & 1 deletion packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts
@@ -1,5 +1,7 @@
import type { TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
import * as tsutils from 'ts-api-utils';
import type * as ts from 'typescript';

import {
createRule,
Expand Down Expand Up @@ -51,6 +53,16 @@ export default createRule({
const services = getParserServices(context);
const checker = services.program.getTypeChecker();

function isArrayType(type: ts.Type): boolean {
return tsutils
.unionTypeParts(type)
.every(unionPart =>
tsutils
.intersectionTypeParts(unionPart)
.every(t => checker.isArrayType(t) || checker.isTupleType(t)),
);
}

return {
'CallExpression > MemberExpression.callee'(
callee: MemberExpressionWithCallExpressionParent,
Expand All @@ -72,7 +84,7 @@ export default createRule({
);

// Check the owner type of the `reduce` method.
if (checker.isArrayType(calleeObjType)) {
if (isArrayType(calleeObjType)) {
context.report({
messageId: 'preferTypeParameter',
node: secondArg,
Expand Down
Expand Up @@ -39,6 +39,24 @@ ruleTester.run('prefer-reduce-type-parameter', rule, {
'[1, 2, 3].reduce((sum, num) => sum + num, 0);',
'[1, 2, 3].reduce<number[]>((a, s) => a.concat(s * 2), []);',
'[1, 2, 3]?.reduce<number[]>((a, s) => a.concat(s * 2), []);',
`
declare const tuple: [number, number, number];
tuple.reduce<number[]>((a, s) => a.concat(s * 2), []);
`,
`
type Reducer = { reduce: (callback: (arg: any) => any, arg: any) => any };
declare const tuple: [number, number, number] | Reducer;
tuple.reduce(a => {
return a.concat(1);
}, [] as number[]);
`,
`
type Reducer = { reduce: (callback: (arg: any) => any, arg: any) => any };
declare const arrayOrReducer: number[] & Reducer;
arrayOrReducer.reduce(a => {
return a.concat(1);
}, [] as number[]);
`,
],
invalid: [
{
Expand Down Expand Up @@ -206,5 +224,56 @@ function f<T, U extends T[]>(a: U) {
},
],
},
{
code: `
declare const tuple: [number, number, number];
tuple.reduce((a, s) => a.concat(s * 2), [] as number[]);
`,
output: `
declare const tuple: [number, number, number];
tuple.reduce<number[]>((a, s) => a.concat(s * 2), []);
`,
errors: [
{
messageId: 'preferTypeParameter',
column: 41,
line: 3,
},
],
},
{
code: `
declare const tupleOrArray: [number, number, number] | number[];
tupleOrArray.reduce((a, s) => a.concat(s * 2), [] as number[]);
`,
output: `
declare const tupleOrArray: [number, number, number] | number[];
tupleOrArray.reduce<number[]>((a, s) => a.concat(s * 2), []);
`,
errors: [
{
messageId: 'preferTypeParameter',
column: 48,
line: 3,
},
],
},
{
code: `
declare const tuple: [number, number, number] & number[];
tuple.reduce((a, s) => a.concat(s * 2), [] as number[]);
`,
output: `
declare const tuple: [number, number, number] & number[];
tuple.reduce<number[]>((a, s) => a.concat(s * 2), []);
`,
errors: [
{
messageId: 'preferTypeParameter',
column: 41,
line: 3,
},
],
},
],
});

0 comments on commit a61eecc

Please sign in to comment.