Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix(eslint-plugin): [use-unknown-in-catch-callback-variable] only flag function literals#10436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,10 +100,41 @@ export default createRule<[], MessageIds>({
return false;
}

function shouldFlagArgument(node: TSESTree.Expression): boolean {
const argument = esTreeNodeToTSNodeMap.get(node);
const typeOfArgument = checker.getTypeAtLocation(argument);
return isFlaggableHandlerType(typeOfArgument);
function collectFlaggedNodes(
node: Exclude<TSESTree.Node, TSESTree.SpreadElement>,
): (TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression)[] {
switch (node.type) {
case AST_NODE_TYPES.LogicalExpression:
return [
...collectFlaggedNodes(node.left),
...collectFlaggedNodes(node.right),
];
case AST_NODE_TYPES.SequenceExpression:
return collectFlaggedNodes(
nullThrows(
node.expressions.at(-1),
'sequence expression must have multiple expressions',
),
);
case AST_NODE_TYPES.ConditionalExpression:
return [
...collectFlaggedNodes(node.consequent),
...collectFlaggedNodes(node.alternate),
];
case AST_NODE_TYPES.ArrowFunctionExpression:
case AST_NODE_TYPES.FunctionExpression:
{
const argument = esTreeNodeToTSNodeMap.get(node);
const typeOfArgument = checker.getTypeAtLocation(argument);
if (isFlaggableHandlerType(typeOfArgument)) {
return [node];
}
}
break;
default:
break;
}
return [];
}

/**
Expand All@@ -114,18 +145,8 @@ export default createRule<[], MessageIds>({
* rule _is reporting_, so it is not guaranteed to be sound to call otherwise.
*/
function refineReportIfPossible(
argument: TSESTree.Expression,
argument: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression,
): Partial<ReportDescriptor<MessageIds>> | undefined {
// Only know how to be helpful if a function literal has been provided.
if (
!(
argument.type === AST_NODE_TYPES.ArrowFunctionExpression ||
argument.type === AST_NODE_TYPES.FunctionExpression
)
) {
return undefined;
}

const catchVariableOuterWithIncorrectTypes = nullThrows(
argument.params.at(0),
'There should have been at least one parameter for the rule to have flagged.',
Expand DownExpand Up@@ -277,11 +298,12 @@ export default createRule<[], MessageIds>({
}

// the `some` check above has already excluded `SpreadElement`, so we are safe to assert the same
constnode = argsToCheck[argIndexToCheck] as Exclude<
(typeof argsToCheck)[number],
constargToCheck = argsToCheck[argIndexToCheck] as Exclude<
TSESTree.Node,
TSESTree.SpreadElement
>;
if (shouldFlagArgument(node)) {

for (const node of collectFlaggedNodes(argToCheck)) {
// We are now guaranteed to report, but we have a bit of work to do
// to determine exactly where, and whether we can fix it.
const overrides = refineReportIfPossible(node);
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -163,6 +163,21 @@ Promise.resolve().catch(...x);
declare const thenArgs: [() => {}, (err: any) => {}];
Promise.resolve().then(...thenArgs);
`,
// this is valid, because the `any` is a passed-in handler, not a function literal.
// https://github.com/typescript-eslint/typescript-eslint/issues/9057
`
declare const yoloHandler: (x: any) => void;
Promise.reject(new Error('I will reject!')).catch(yoloHandler);
`,
// type assertion is not a function literal.
`
type InvalidHandler = (arg: any) => void;
Promise.resolve().catch(<InvalidHandler>(
function (err /* awkward spot for comment */) {
throw err;
}
));
`,
],

invalid: [
Expand DownExpand Up@@ -347,25 +362,6 @@ Promise.resolve().catch(function (err: unknown /* awkward spot for comment */) {
],
},

{
code: `
type InvalidHandler = (arg: any) => void;
Promise.resolve().catch(<InvalidHandler>(
function (err /* awkward spot for comment */) {
throw err;
}
));
`,
errors: [
{
line: 3,
messageId: 'useUnknown',
// We should _not_ make a suggestion due to the type assertion.
suggestions: null,
},
],
},

{
code: `
Promise.resolve().catch(function namedCallback(err: string) {
Expand DownExpand Up@@ -598,19 +594,6 @@ Promise.reject(new Error('I will reject!')).catch(([err]: [unknown]) => {
],
},

{
code: `
declare const yoloHandler: (x: any) => void;
Promise.reject(new Error('I will reject!')).catch(yoloHandler);
`,
errors: [
{
line: 3,
messageId: 'useUnknown',
},
],
},

{
code: `
Promise.resolve(' a string ').catch(
Expand DownExpand Up@@ -748,5 +731,132 @@ Promise.resolve().catch((...{ find }: [unknown]) => {
},
],
},

{
code: `
declare const condition: boolean;
Promise.resolve('foo').then(() => {}, condition ? err => {} : err => {});
`,
errors: [
{
column: 51,
endColumn: 54,
endLine: 3,
line: 3,

messageId: 'useUnknown',

suggestions: [
{
messageId: 'addUnknownTypeAnnotationSuggestion',
output: `
declare const condition: boolean;
Promise.resolve('foo').then(() => {}, condition ? (err: unknown) => {} : err => {});
`,
},
],
},
{
column: 63,
endColumn: 66,
endLine: 3,
line: 3,

messageId: 'useUnknown',

suggestions: [
{
messageId: 'addUnknownTypeAnnotationSuggestion',
output: `
declare const condition: boolean;
Promise.resolve('foo').then(() => {}, condition ? err => {} : (err: unknown) => {});
`,
},
],
},
],
},
{
code: `
declare const condition: boolean;
declare const maybeNullishHandler: null | ((err: any) => void);
Promise.resolve('foo').catch(
condition
? (err => {}, err => {}, maybeNullishHandler) ?? (err => {})
: (condition && (err => {})) || (err => {}),
);
`,
errors: [
{
column: 55,
endColumn: 58,
endLine: 6,
line: 6,

messageId: 'useUnknown',

suggestions: [
{
messageId: 'addUnknownTypeAnnotationSuggestion',
output: `
declare const condition: boolean;
declare const maybeNullishHandler: null | ((err: any) => void);
Promise.resolve('foo').catch(
condition
? (err => {}, err => {}, maybeNullishHandler) ?? ((err: unknown) => {})
: (condition && (err => {})) || (err => {}),
);
`,
},
],
},
{
column: 22,
endColumn: 25,
endLine: 7,
line: 7,

messageId: 'useUnknown',

suggestions: [
{
messageId: 'addUnknownTypeAnnotationSuggestion',
output: `
declare const condition: boolean;
declare const maybeNullishHandler: null | ((err: any) => void);
Promise.resolve('foo').catch(
condition
? (err => {}, err => {}, maybeNullishHandler) ?? (err => {})
: (condition && ((err: unknown) => {})) || (err => {}),
);
`,
},
],
},
{
column: 38,
endColumn: 41,
endLine: 7,
line: 7,

messageId: 'useUnknown',

suggestions: [
{
messageId: 'addUnknownTypeAnnotationSuggestion',
output: `
declare const condition: boolean;
declare const maybeNullishHandler: null | ((err: any) => void);
Promise.resolve('foo').catch(
condition
? (err => {}, err => {}, maybeNullishHandler) ?? (err => {})
: (condition && (err => {})) || ((err: unknown) => {}),
);
`,
},
],
},
],
},
],
});
Loading

[8]ページ先頭

©2009-2025 Movatter.jp