Skip to content

Commit

Permalink
feat: require-array-sort-compare + toSorted (#8052)
Browse files Browse the repository at this point in the history
* feat: toSorted works

* refactor: add test
  • Loading branch information
Zamiell committed Dec 12, 2023
1 parent 7ec3022 commit c9661c8
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 17 deletions.
Expand Up @@ -6,7 +6,7 @@ description: 'Require `Array#sort` calls to always provide a `compareFunction`.'
>
> See **https://typescript-eslint.io/rules/require-array-sort-compare** for documentation.
When called without a compare function, `Array#sort()` converts all non-undefined array elements into strings and then compares said strings based off their UTF-16 code units [[ECMA specification](https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare)].
When called without a compare function, `Array#sort()` and `Array#toSorted()` converts all non-undefined array elements into strings and then compares said strings based off their UTF-16 code units [[ECMA specification](https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare)].

The result is that elements are sorted alphabetically, regardless of their type.
For example, when sorting numbers, this results in a "10 before 2" order:
Expand Down
35 changes: 19 additions & 16 deletions packages/eslint-plugin/src/rules/require-array-sort-compare.ts
Expand Up @@ -27,7 +27,7 @@ export default createRule<Options, MessageIds>({
type: 'problem',
docs: {
description:
'Require `Array#sort` calls to always provide a `compareFunction`',
'Require `Array#sort` and `Array#toSorted` calls to always provide a `compareFunction`',
requiresTypeChecking: true,
},
messages: {
Expand Down Expand Up @@ -66,23 +66,26 @@ export default createRule<Options, MessageIds>({
return false;
}

return {
"CallExpression[arguments.length=0] > MemberExpression[property.name='sort'][computed=false]"(
callee: TSESTree.MemberExpression,
): void {
const calleeObjType = getConstrainedTypeAtLocation(
services,
callee.object,
);
function checkSortArgument(callee: TSESTree.MemberExpression): void {
const calleeObjType = getConstrainedTypeAtLocation(
services,
callee.object,
);

if (options.ignoreStringArrays && isStringArrayNode(callee.object)) {
return;
}
if (options.ignoreStringArrays && isStringArrayNode(callee.object)) {
return;
}

if (isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) {
context.report({ node: callee.parent, messageId: 'requireCompare' });
}
},
if (isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) {
context.report({ node: callee.parent, messageId: 'requireCompare' });
}
}

return {
"CallExpression[arguments.length=0] > MemberExpression[property.name='sort'][computed=false]":
checkSortArgument,
"CallExpression[arguments.length=0] > MemberExpression[property.name='toSorted'][computed=false]":
checkSortArgument,
};
},
});
Expand Up @@ -126,6 +126,13 @@ ruleTester.run('require-array-sort-compare', rule, {
`,
options: [{ ignoreStringArrays: true }],
},
{
code: `
function f(a: number[]) {
a.toSorted((a, b) => a - b);
}
`,
},
],
invalid: [
{
Expand Down Expand Up @@ -254,5 +261,13 @@ ruleTester.run('require-array-sort-compare', rule, {
errors: [{ messageId: 'requireCompare' }],
options: [{ ignoreStringArrays: true }],
},
{
code: `
function f(a: number[]) {
a.toSorted();
}
`,
errors: [{ messageId: 'requireCompare' }],
},
],
});

0 comments on commit c9661c8

Please sign in to comment.