Skip to content

Commit

Permalink
feat(eslint-plugin): [prefer-readonly-parameter-types] add `ignoreInf…
Browse files Browse the repository at this point in the history
…erredTypes` option (#2668)
  • Loading branch information
eyelidlessness committed Oct 18, 2020
1 parent da71362 commit 91010e8
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
Expand Up @@ -124,10 +124,12 @@ interface Foo {
```ts
interface Options {
checkParameterProperties?: boolean;
ignoreInferredTypes?: boolean;
}

const defaultOptions: Options = {
checkParameterProperties: true,
ignoreInferredTypes: false,
};
```

Expand Down Expand Up @@ -162,3 +164,53 @@ class Foo {
) {}
}
```

### `ignoreInferredTypes`

This option allows you to ignore parameters which don't explicitly specify a type. This may be desirable in cases where an external dependency specifies a callback with mutable parameters, and manually annotating the callback's parameters is undesirable.

Examples of **incorrect** code for this rule with `{ignoreInferredTypes: true}`:

```ts
import { acceptsCallback, CallbackOptions } from 'external-dependency';

acceceptsCallback((options: CallbackOptions) => {});
```

<details>
<summary>external-dependency.d.ts</summary>

```ts
export interface CallbackOptions {
prop: string;
}
type Callback = (options: CallbackOptions) => void;
type AcceptsCallback = (callback: Callback) => void;

export const acceptsCallback: AcceptsCallback;
```

</details>

Examples of **correct** code for this rule with `{ignoreInferredTypes: true}`:

```ts
import { acceptsCallback } from 'external-dependency';

acceceptsCallback(options => {});
```

<details>
<summary>external-dependency.d.ts</summary>

```ts
export interface CallbackOptions {
prop: string;
}
type Callback = (options: CallbackOptions) => void;
type AcceptsCallback = (callback: Callback) => void;

export const acceptsCallback: AcceptsCallback;
```

</details>
Expand Up @@ -7,6 +7,7 @@ import * as util from '../util';
type Options = [
{
checkParameterProperties?: boolean;
ignoreInferredTypes?: boolean;
},
];
type MessageIds = 'shouldBeReadonly';
Expand All @@ -30,6 +31,9 @@ export default util.createRule<Options, MessageIds>({
checkParameterProperties: {
type: 'boolean',
},
ignoreInferredTypes: {
type: 'boolean',
},
},
},
],
Expand All @@ -40,9 +44,11 @@ export default util.createRule<Options, MessageIds>({
defaultOptions: [
{
checkParameterProperties: true,
ignoreInferredTypes: false,
},
],
create(context, [{ checkParameterProperties }]) {
create(context, options) {
const [{ checkParameterProperties, ignoreInferredTypes }] = options;
const { esTreeNodeToTSNodeMap, program } = util.getParserServices(context);
const checker = program.getTypeChecker();

Expand Down Expand Up @@ -81,6 +87,11 @@ export default util.createRule<Options, MessageIds>({
param.type === AST_NODE_TYPES.TSParameterProperty
? param.parameter
: param;

if (ignoreInferredTypes && actualParam.typeAnnotation == null) {
continue;
}

const tsNode = esTreeNodeToTSNodeMap.get(actualParam);
const type = checker.getTypeAtLocation(tsNode);
const isReadOnly = util.isTypeReadonly(checker, type);
Expand Down
Expand Up @@ -247,6 +247,24 @@ ruleTester.run('prefer-readonly-parameter-types', rule, {
const willNotCrash = (foo: Readonly<WithSymbol>) => {};
`,
{
code: `
type Callback<T> = (options: T) => void;
declare const acceptsCallback: <T>(callback: Callback<T>) => void;
interface CallbackOptions {
prop: string;
}
acceptsCallback<CallbackOptions>(options => {});
`,
options: [
{
ignoreInferredTypes: true,
},
],
},
],
invalid: [
// arrays
Expand Down Expand Up @@ -671,5 +689,31 @@ ruleTester.run('prefer-readonly-parameter-types', rule, {
},
],
},
{
code: `
type Callback<T> = (options: T) => void;
declare const acceptsCallback: <T>(callback: Callback<T>) => void;
interface CallbackOptions {
prop: string;
}
acceptsCallback<CallbackOptions>((options: CallbackOptions) => {});
`,
options: [
{
ignoreInferredTypes: true,
},
],
errors: [
{
messageId: 'shouldBeReadonly',
line: 10,
column: 43,
endColumn: 67,
},
],
},
],
});

0 comments on commit 91010e8

Please sign in to comment.