Skip to content

Commit 9e7d161

Browse files
authored
fix(eslint-plugin): [embt] fix allowTypedFunctionExpressions (typescript-eslint#1553)
1 parent 45ae0b9 commit 9e7d161

File tree

4 files changed

+156
-96
lines changed

4 files changed

+156
-96
lines changed

packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,26 @@ The rule accepts an options object with the following properties:
6565

6666
```ts
6767
type Options = {
68-
// if true, type annotations are also allowed on the variable of a function expression rather than on the function directly
68+
/**
69+
* If true, type annotations are also allowed on the variable of a function expression
70+
* rather than on the function arguments/return value directly.
71+
*/
6972
allowTypedFunctionExpressions?: boolean;
70-
// if true, functions immediately returning another function expression will not be checked
73+
/**
74+
* If true, functions immediately returning another function expression will not
75+
* require an explicit return value annotation.
76+
* You must still type the parameters of the function.
77+
*/
7178
allowHigherOrderFunctions?: boolean;
72-
// if true, body-less arrow functions are allowed to return an object as const
79+
/**
80+
* If true, body-less arrow functions that return an `as const` type assertion will not
81+
* require an explicit return value annotation.
82+
* You must still type the parameters of the function.
83+
*/
7384
allowDirectConstAssertionInArrowFunctions?: boolean;
74-
// an array of function/method names that will not be checked
85+
/**
86+
* An array of function/method names that will not have their arguments or their return values checked.
87+
*/
7588
allowedNames?: string[];
7689
};
7790

@@ -118,6 +131,8 @@ export let funcExpr = function() {
118131
export let objectProp = {
119132
foo: () => 1,
120133
};
134+
135+
export const foo = bar => {};
121136
```
122137

123138
Examples of additional **correct** code for this rule with `{ allowTypedFunctionExpressions: true }`:
@@ -146,6 +161,9 @@ export let objectPropAs = {
146161
export let objectPropCast = <ObjectType>{
147162
foo: () => 1,
148163
};
164+
165+
type FooType = (bar: string) => void;
166+
export const foo: FooType = bar => {};
149167
```
150168

151169
### `allowHigherOrderFunctions`
@@ -158,6 +176,10 @@ export var arrowFn = () => () => {};
158176
export function fn() {
159177
return function() {};
160178
}
179+
180+
export function foo(outer) {
181+
return function(inner): void {};
182+
}
161183
```
162184

163185
Examples of **correct** code for this rule with `{ allowHigherOrderFunctions: true }`:
@@ -168,17 +190,15 @@ export var arrowFn = () => (): void => {};
168190
export function fn() {
169191
return function(): void {};
170192
}
193+
194+
export function foo(outer: string) {
195+
return function(inner: string): void {};
196+
}
171197
```
172198

173199
### `allowDirectConstAssertionInArrowFunctions`
174200

175-
Examples of additional **correct** code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`:
176-
177-
```ts
178-
export const func = (value: number) => ({ type: 'X', value } as const);
179-
```
180-
181-
Examples of additional **incorrect** code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`:
201+
Examples of **incorrect** code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`:
182202

183203
```ts
184204
export const func = (value: number) => ({ type: 'X', value });
@@ -187,15 +207,34 @@ export const foo = () => {
187207
bar: true,
188208
} as const;
189209
};
210+
export const bar = () => 1;
211+
export const baz = arg => arg as const;
212+
```
213+
214+
Examples of **correct** code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`:
215+
216+
```ts
217+
export const func = (value: number) => ({ type: 'X', value } as const);
218+
export const foo = () =>
219+
({
220+
bar: true,
221+
} as const);
222+
export const bar = () => 1 as const;
223+
export const baz = (arg: string) => arg as const;
190224
```
191225

192226
### `allowedNames`
193227

194228
You may pass function/method names you would like this rule to ignore, like so:
195229

196-
```cjson
230+
```json
197231
{
198-
"@typescript-eslint/explicit-module-boundary-types": ["error", { "allowedName": ["ignoredFunctionName", "ignoredMethodName"] }]
232+
"@typescript-eslint/explicit-module-boundary-types": [
233+
"error",
234+
{
235+
"allowedName": ["ignoredFunctionName", "ignoredMethodName"]
236+
}
237+
]
199238
}
200239
```
201240

packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as util from '../util';
66
import {
77
checkFunctionExpressionReturnType,
88
checkFunctionReturnType,
9+
isTypedFunctionExpression,
910
} from '../util/explicitReturnTypeUtils';
1011

1112
type Options = [
@@ -178,7 +179,11 @@ export default util.createRule<Options, MessageIds>({
178179
return;
179180
}
180181

181-
if (isAllowedName(node.parent) || isUnexported(node)) {
182+
if (
183+
isAllowedName(node.parent) ||
184+
isUnexported(node) ||
185+
isTypedFunctionExpression(node, options)
186+
) {
182187
return;
183188
}
184189

packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
AST_TOKEN_TYPES,
66
} from '@typescript-eslint/experimental-utils';
77
import { isTypeAssertion, isConstructor, isSetter } from './astUtils';
8+
import { nullThrows, NullThrowsReasons } from './nullThrows';
89

910
type FunctionNode =
1011
| TSESTree.ArrowFunctionExpression
@@ -264,6 +265,26 @@ function checkFunctionReturnType(
264265
report(getReporLoc(node, sourceCode));
265266
}
266267

268+
function isTypedFunctionExpression(
269+
node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression,
270+
options: Options,
271+
): boolean {
272+
const parent = nullThrows(node.parent, NullThrowsReasons.MissingParent);
273+
274+
if (!options.allowTypedFunctionExpressions) {
275+
return false;
276+
}
277+
278+
return (
279+
isTypeAssertion(parent) ||
280+
isVariableDeclaratorWithTypeAnnotation(parent) ||
281+
isClassPropertyWithTypeAnnotation(parent) ||
282+
isPropertyOfObjectWithType(parent) ||
283+
isFunctionArgument(parent, node) ||
284+
isConstructorArgument(parent)
285+
);
286+
}
287+
267288
/**
268289
* Checks if a function declaration/expression has a return type.
269290
*/
@@ -273,36 +294,25 @@ function checkFunctionExpressionReturnType(
273294
sourceCode: TSESLint.SourceCode,
274295
report: (loc: TSESTree.SourceLocation) => void,
275296
): void {
276-
// Should always have a parent; checking just in case
277-
/* istanbul ignore else */ if (node.parent) {
278-
if (options.allowTypedFunctionExpressions) {
279-
if (
280-
isTypeAssertion(node.parent) ||
281-
isVariableDeclaratorWithTypeAnnotation(node.parent) ||
282-
isClassPropertyWithTypeAnnotation(node.parent) ||
283-
isPropertyOfObjectWithType(node.parent) ||
284-
isFunctionArgument(node.parent, node) ||
285-
isConstructorArgument(node.parent)
286-
) {
287-
return;
288-
}
289-
}
297+
if (isTypedFunctionExpression(node, options)) {
298+
return;
299+
}
290300

291-
if (
292-
options.allowExpressions &&
293-
node.parent.type !== AST_NODE_TYPES.VariableDeclarator &&
294-
node.parent.type !== AST_NODE_TYPES.MethodDefinition &&
295-
node.parent.type !== AST_NODE_TYPES.ExportDefaultDeclaration &&
296-
node.parent.type !== AST_NODE_TYPES.ClassProperty
297-
) {
298-
return;
299-
}
301+
const parent = nullThrows(node.parent, NullThrowsReasons.MissingParent);
302+
if (
303+
options.allowExpressions &&
304+
parent.type !== AST_NODE_TYPES.VariableDeclarator &&
305+
parent.type !== AST_NODE_TYPES.MethodDefinition &&
306+
parent.type !== AST_NODE_TYPES.ExportDefaultDeclaration &&
307+
parent.type !== AST_NODE_TYPES.ClassProperty
308+
) {
309+
return;
300310
}
301311

302312
// https://github.com/typescript-eslint/typescript-eslint/issues/653
303313
if (
304-
node.type === AST_NODE_TYPES.ArrowFunctionExpression &&
305314
options.allowDirectConstAssertionInArrowFunctions &&
315+
node.type === AST_NODE_TYPES.ArrowFunctionExpression &&
306316
returnsConstAssertionDirectly(node)
307317
) {
308318
return;
@@ -311,4 +321,8 @@ function checkFunctionExpressionReturnType(
311321
checkFunctionReturnType(node, options, sourceCode, report);
312322
}
313323

314-
export { checkFunctionReturnType, checkFunctionExpressionReturnType };
324+
export {
325+
checkFunctionReturnType,
326+
checkFunctionExpressionReturnType,
327+
isTypedFunctionExpression,
328+
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy