feat: inferred types rule

Added typescript rule for inferred types. By default all types must
be explicit, but this can be changed by a user option.
The JSDocs type implementation will be added in the future
This commit is contained in:
Guz013
2023-07-13 19:03:40 -03:00
parent 37d7f473bb
commit e7b4a7b280
2 changed files with 117 additions and 0 deletions

View File

@@ -2,6 +2,18 @@ import type { Linter } from 'eslint';
export type ESConfig = Readonly<Linter.FlatConfig>;
export type inferrableTypesOptions = [
'never' | 'always' | 'ts-never' | 'js-never',
{
/** @see {@link https://typescript-eslint.io/rules/no-inferrable-types#ignoreparameters} */
parameters?: boolean
/** @see {@link https://typescript-eslint.io/rules/no-inferrable-types#ignoreproperties} */
properties?: boolean
/** @see {@link https://typescript-eslint.io/rules/explicit-function-return-type} */
returnValues?: boolean
},
] | 'never' | 'always' | 'ts-never' | 'js-never';
export interface Config {
tsconfig?: string | string[]
strict?: boolean
@@ -9,5 +21,80 @@ export interface Config {
indent?: 'tab' | 'space'
quotes?: 'single' | 'double'
semi?: 'never' | 'always'
/**
* Typescript's type-checking is able to infer types from parameters.
* So using an explicit `:` type annotation isn't obligatory.
*
* But, by default, type annotations are always mandated to make
* the core more readable, explicit and robust to changes.
*
* See {@link https://typescript-eslint.io/rules/no-inferrable-types typescript-eslint documentation }
* for more info.
* ---
* *Note: The JSDocs examples are with invalid {@link https://jsdoc.app/tags-type.html JSDoc (at)type}
* syntax unfortunately, as using it would break this documentation display.*
* ---
* **Option: `never`** (default)
* Types are always explicit in Javascript (using JSDocs) and Typescript
*
* @example ```js
// Javascript
//** type {number} *
const id = 10;
//** type {string} *
const name = 'foo';
```
* @example ```ts
// Typescript
const id: number = 10;
const name: string = 'foo';
```
* ---
* **Option: `always`**
* Types are always inferred in Javascript and Typescript
*
* @example ```js
// Javascript
const id = 10;
const name = 'foo';
```
* @example ```ts
// Typescript
const id = 10;
const name = 'foo';
```
* ---
* **Option: `ts-never`**
* Types are always explicit in Typescript, but inferred in Javascript
*
* @example ```js
// Javascript
const id = 10;
const name = 'foo';
```
* @example ```ts
// Typescript
const id: number = 10;
const name: string = 'foo';
```
* ---
* **Option: `js-never`** (default)
* Types are always explicit in Javascript (with JSDocs), but inferred in Typescript
*
* @example ```js
// Javascript
//** type {number} *
const id = 10;
//** type {string} *
const name = 'foo';
```
* @example ```ts
// Typescript
const id = 10;
const name = 'foo';
```
* ---
*/
inferrableTypes?: inferrableTypesOptions
}
}

View File

@@ -16,5 +16,35 @@ export function getUserRules(userOptions) {
configs.formatting.rules['@typescript-eslint/indent'][2] ?? null,
],
},
},
{
files: ['**/*.ts'],
rules: {
...(
/** @type {() => import('eslint').Linter.RulesRecord} */
() => {
const inferrableTypes = userOptions?.inferrableTypes ?? 'never';
if (typeof inferrableTypes === 'string') {
return {
'@typescript-eslint/explicit-function-return-type': inferrableTypes === 'always' ? 'off' : 'error',
'@typescript-eslint/no-inferrable-types': inferrableTypes === 'always' ? 'off' : 'error',
};
}
else {
return {
'@typescript-eslint/explicit-function-return-type': inferrableTypes[1].returnValues ? 'off' : 'error',
'@typescript-eslint/no-inferrable-types': [
inferrableTypes[0] === 'always' ? 'off' : 'error',
{
ignoreParameters: inferrableTypes[1].parameters ?? false,
ignoreProperties: inferrableTypes[1].properties ?? false,
},
],
};
}
})(),
},
}];
}