-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(eslint-plugin): add explicit-module-boundary-types rule (#1020)
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
- Loading branch information
1 parent
61eb434
commit bb0a846
Showing
7 changed files
with
1,480 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
208 changes: 208 additions & 0 deletions
208
packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
# Require explicit return and argument types on exported functions' and classes' public class methods (`explicit-module-boundary-types`) | ||
|
||
Explicit types for function return values and arguments makes it clear to any calling code what is the module boundary's input and output. | ||
|
||
Consider using this rule in place of [`no-untyped-public-signature`](./no-untyped-public-signature.md) which has been deprecated. | ||
|
||
## Rule Details | ||
|
||
This rule aims to ensure that the values returned from a module are of the expected type. | ||
|
||
The following patterns are considered warnings: | ||
|
||
```ts | ||
// Should indicate that no value is returned (void) | ||
export function test() { | ||
return; | ||
} | ||
|
||
// Should indicate that a number is returned | ||
export default function() { | ||
return 1; | ||
} | ||
|
||
// Should indicate that a string is returned | ||
export var arrowFn = () => 'test'; | ||
|
||
// All arguments should be typed | ||
export var arrowFn = (arg): string => `test ${arg}`; | ||
|
||
export class Test { | ||
// Should indicate that no value is returned (void) | ||
method() { | ||
return; | ||
} | ||
} | ||
``` | ||
|
||
The following patterns are not warnings: | ||
|
||
```ts | ||
// Function is not exported | ||
function test() { | ||
return; | ||
} | ||
|
||
// A return value of type number | ||
export var fn = function(): number { | ||
return 1; | ||
}; | ||
|
||
// A return value of type string | ||
export var arrowFn = (arg: string): string => `test ${arg}`; | ||
|
||
// Class is not exported | ||
class Test { | ||
method() { | ||
return; | ||
} | ||
} | ||
``` | ||
|
||
## Options | ||
|
||
The rule accepts an options object with the following properties: | ||
|
||
```ts | ||
type Options = { | ||
// if true, type annotations are also allowed on the variable of a function expression rather than on the function directly | ||
allowTypedFunctionExpressions?: boolean; | ||
// if true, functions immediately returning another function expression will not be checked | ||
allowHigherOrderFunctions?: boolean; | ||
// if true, body-less arrow functions are allowed to return an object as const | ||
allowDirectConstAssertionInArrowFunctions?: boolean; | ||
// an array of function/method names that will not be checked | ||
allowedNames?: string[]; | ||
}; | ||
|
||
const defaults = { | ||
allowTypedFunctionExpressions: true, | ||
allowHigherOrderFunctions: true, | ||
allowedNames: [], | ||
}; | ||
``` | ||
|
||
### Configuring in a mixed JS/TS codebase | ||
|
||
If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.jsx` files. | ||
|
||
```jsonc | ||
{ | ||
"rules": { | ||
// disable the rule for all files | ||
"@typescript-eslint/explicit-module-boundary-types": "off" | ||
}, | ||
"overrides": [ | ||
{ | ||
// enable the rule specifically for TypeScript files | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": { | ||
"@typescript-eslint/explicit-module-boundary-types": ["error"] | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
|
||
### `allowTypedFunctionExpressions` | ||
|
||
Examples of **incorrect** code for this rule with `{ allowTypedFunctionExpressions: true }`: | ||
|
||
```ts | ||
export let arrowFn = () => 'test'; | ||
|
||
export let funcExpr = function() { | ||
return 'test'; | ||
}; | ||
|
||
export let objectProp = { | ||
foo: () => 1, | ||
}; | ||
``` | ||
|
||
Examples of additional **correct** code for this rule with `{ allowTypedFunctionExpressions: true }`: | ||
|
||
```ts | ||
type FuncType = () => string; | ||
|
||
export let arrowFn: FuncType = () => 'test'; | ||
|
||
export let funcExpr: FuncType = function() { | ||
return 'test'; | ||
}; | ||
|
||
export let asTyped = (() => '') as () => string; | ||
export let castTyped = <() => string>(() => ''); | ||
|
||
interface ObjectType { | ||
foo(): number; | ||
} | ||
export let objectProp: ObjectType = { | ||
foo: () => 1, | ||
}; | ||
export let objectPropAs = { | ||
foo: () => 1, | ||
} as ObjectType; | ||
export let objectPropCast = <ObjectType>{ | ||
foo: () => 1, | ||
}; | ||
``` | ||
|
||
### `allowHigherOrderFunctions` | ||
|
||
Examples of **incorrect** code for this rule with `{ allowHigherOrderFunctions: true }`: | ||
|
||
```ts | ||
export var arrowFn = () => () => {}; | ||
|
||
export function fn() { | ||
return function() {}; | ||
} | ||
``` | ||
|
||
Examples of **correct** code for this rule with `{ allowHigherOrderFunctions: true }`: | ||
|
||
```ts | ||
export var arrowFn = () => (): void => {}; | ||
|
||
export function fn() { | ||
return function(): void {}; | ||
} | ||
``` | ||
|
||
### `allowDirectConstAssertionInArrowFunctions` | ||
|
||
Examples of additional **correct** code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`: | ||
|
||
```ts | ||
export const func = (value: number) => ({ type: 'X', value } as const); | ||
``` | ||
|
||
Examples of additional **incorrect** code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`: | ||
|
||
```ts | ||
export const func = (value: number) => ({ type: 'X', value }); | ||
export const foo = () => { | ||
return { | ||
bar: true, | ||
} as const; | ||
}; | ||
``` | ||
|
||
### `allowedNames` | ||
|
||
You may pass function/method names you would like this rule to ignore, like so: | ||
|
||
```cjson | ||
{ | ||
"@typescript-eslint/explicit-module-boundary-types": ["error", { "allowedName": ["ignoredFunctionName", "ignoredMethodName"] }] | ||
} | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
If you wish to make sure all functions have explicit return types, as opposed to only the module boundaries, you can use [explicit-function-return-type](https://github.com/eslint/eslint/blob/master/docs/rules/explicit-function-return-type.md) | ||
|
||
## Further Reading | ||
|
||
- TypeScript [Functions](https://www.typescriptlang.org/docs/handbook/functions.html#function-types) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.