eslint-plugin-typefest 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -3
- package/dist/_internal/constrained-type-at-location.d.ts.map +1 -1
- package/dist/_internal/constrained-type-at-location.js.map +1 -1
- package/dist/_internal/function-type-reference-patterns.d.ts +34 -0
- package/dist/_internal/function-type-reference-patterns.d.ts.map +1 -0
- package/dist/_internal/function-type-reference-patterns.js +103 -0
- package/dist/_internal/function-type-reference-patterns.js.map +1 -0
- package/dist/_internal/rule-catalog.d.ts.map +1 -1
- package/dist/_internal/rule-catalog.js +11 -0
- package/dist/_internal/rule-catalog.js.map +1 -1
- package/dist/_internal/rules-registry.d.ts.map +1 -1
- package/dist/_internal/rules-registry.js +22 -0
- package/dist/_internal/rules-registry.js.map +1 -1
- package/dist/_internal/set-membership.d.ts.map +1 -1
- package/dist/_internal/set-membership.js.map +1 -1
- package/dist/_internal/type-checker-compat.d.ts.map +1 -1
- package/dist/_internal/type-checker-compat.js.map +1 -1
- package/dist/_internal/type-reference-node.d.ts +8 -0
- package/dist/_internal/type-reference-node.d.ts.map +1 -1
- package/dist/_internal/type-reference-node.js +14 -0
- package/dist/_internal/type-reference-node.js.map +1 -1
- package/dist/_internal/typefest-config-references.d.ts +2 -1
- package/dist/_internal/typefest-config-references.d.ts.map +1 -1
- package/dist/_internal/typefest-config-references.js +11 -2
- package/dist/_internal/typefest-config-references.js.map +1 -1
- package/dist/_internal/typescript-eslint-node-autofix.js.map +1 -1
- package/dist/plugin.cjs +1069 -117
- package/dist/plugin.cjs.map +4 -4
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +5 -0
- package/dist/plugin.js.map +1 -1
- package/dist/rules/prefer-ts-extras-object-map-values.d.ts +14 -0
- package/dist/rules/prefer-ts-extras-object-map-values.d.ts.map +1 -0
- package/dist/rules/prefer-ts-extras-object-map-values.js +227 -0
- package/dist/rules/prefer-ts-extras-object-map-values.js.map +1 -0
- package/dist/rules/prefer-type-fest-asyncify.d.ts +7 -0
- package/dist/rules/prefer-type-fest-asyncify.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-asyncify.js +79 -0
- package/dist/rules/prefer-type-fest-asyncify.js.map +1 -0
- package/dist/rules/prefer-type-fest-conditional-except.d.ts +7 -0
- package/dist/rules/prefer-type-fest-conditional-except.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-conditional-except.js +94 -0
- package/dist/rules/prefer-type-fest-conditional-except.js.map +1 -0
- package/dist/rules/prefer-type-fest-conditional-keys.d.ts +7 -0
- package/dist/rules/prefer-type-fest-conditional-keys.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-conditional-keys.js +78 -0
- package/dist/rules/prefer-type-fest-conditional-keys.js.map +1 -0
- package/dist/rules/prefer-type-fest-distributed-omit.d.ts +7 -0
- package/dist/rules/prefer-type-fest-distributed-omit.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-distributed-omit.js +67 -0
- package/dist/rules/prefer-type-fest-distributed-omit.js.map +1 -0
- package/dist/rules/prefer-type-fest-distributed-pick.d.ts +7 -0
- package/dist/rules/prefer-type-fest-distributed-pick.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-distributed-pick.js +95 -0
- package/dist/rules/prefer-type-fest-distributed-pick.js.map +1 -0
- package/dist/rules/prefer-type-fest-merge.d.ts +7 -0
- package/dist/rules/prefer-type-fest-merge.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-merge.js +93 -0
- package/dist/rules/prefer-type-fest-merge.js.map +1 -0
- package/dist/rules/prefer-type-fest-pick-index-signature.d.ts +7 -0
- package/dist/rules/prefer-type-fest-pick-index-signature.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-pick-index-signature.js +98 -0
- package/dist/rules/prefer-type-fest-pick-index-signature.js.map +1 -0
- package/dist/rules/prefer-type-fest-set-return-type.d.ts +7 -0
- package/dist/rules/prefer-type-fest-set-return-type.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-set-return-type.js +53 -0
- package/dist/rules/prefer-type-fest-set-return-type.js.map +1 -0
- package/dist/rules/prefer-type-fest-stringified.d.ts +7 -0
- package/dist/rules/prefer-type-fest-stringified.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-stringified.js +73 -0
- package/dist/rules/prefer-type-fest-stringified.js.map +1 -0
- package/dist/rules/prefer-type-fest-union-to-intersection.d.ts +7 -0
- package/dist/rules/prefer-type-fest-union-to-intersection.d.ts.map +1 -0
- package/dist/rules/prefer-type-fest-union-to-intersection.js +114 -0
- package/dist/rules/prefer-type-fest-union-to-intersection.js.map +1 -0
- package/docs/rules/getting-started.md +2 -1
- package/docs/rules/guides/preset-selection-strategy.md +7 -0
- package/docs/rules/overview.md +1 -0
- package/docs/rules/prefer-ts-extras-object-map-values.md +146 -0
- package/docs/rules/prefer-type-fest-asyncify.md +93 -0
- package/docs/rules/prefer-type-fest-conditional-except.md +141 -0
- package/docs/rules/prefer-type-fest-conditional-keys.md +93 -0
- package/docs/rules/prefer-type-fest-distributed-omit.md +92 -0
- package/docs/rules/prefer-type-fest-distributed-pick.md +92 -0
- package/docs/rules/prefer-type-fest-merge.md +161 -0
- package/docs/rules/prefer-type-fest-pick-index-signature.md +93 -0
- package/docs/rules/prefer-type-fest-set-return-type.md +93 -0
- package/docs/rules/prefer-type-fest-stringified.md +134 -0
- package/docs/rules/prefer-type-fest-union-to-intersection.md +118 -0
- package/docs/rules/presets/experimental.md +163 -0
- package/docs/rules/presets/index.md +13 -0
- package/package.json +25 -27
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# prefer-type-fest-distributed-omit
|
|
2
|
+
|
|
3
|
+
Prefer [`DistributedOmit`](https://github.com/sindresorhus/type-fest/blob/main/source/distributed-omit.d.ts) from `type-fest` over distributive conditional helpers built from `Omit`.
|
|
4
|
+
|
|
5
|
+
This rule lives only in the experimental preset and reports without autofixing.
|
|
6
|
+
|
|
7
|
+
## Targeted pattern scope
|
|
8
|
+
|
|
9
|
+
This rule focuses on the common helper shape that distributes `Omit` over a union manually:
|
|
10
|
+
|
|
11
|
+
- `Union extends unknown ? Omit<Union, Key> : never`
|
|
12
|
+
- `Union extends any ? Omit<Union, Key> : never`
|
|
13
|
+
|
|
14
|
+
It intentionally ignores ordinary non-distributive `Omit` usage and unrelated conditional helpers.
|
|
15
|
+
|
|
16
|
+
## What this rule reports
|
|
17
|
+
|
|
18
|
+
This rule reports conditional helpers when all of the following are true:
|
|
19
|
+
|
|
20
|
+
- the false branch is `never`
|
|
21
|
+
- the conditional distributes over the checked type with `extends unknown` or `extends any`
|
|
22
|
+
- the true branch is exactly `Omit<CheckedType, KeyType>`
|
|
23
|
+
|
|
24
|
+
The rule is currently **report-only**. It does not autofix or suggest a replacement yet.
|
|
25
|
+
|
|
26
|
+
## Why this rule exists
|
|
27
|
+
|
|
28
|
+
`DistributedOmit<ObjectType, KeyType>` makes the union-preserving behavior explicit.
|
|
29
|
+
|
|
30
|
+
- Readers do not need to mentally simulate the distributive conditional.
|
|
31
|
+
- The Type-Fest helper explains why this is different from plain `Omit`.
|
|
32
|
+
- Consistent adoption reduces duplicate one-off helpers across a codebase.
|
|
33
|
+
|
|
34
|
+
## ❌ Incorrect
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
type WithoutKeys<Union, Key extends PropertyKey> =
|
|
38
|
+
Union extends unknown ? Omit<Union, Key> : never;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## ✅ Correct
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import type {DistributedOmit} from "type-fest";
|
|
45
|
+
|
|
46
|
+
type WithoutKeys<Union, Key extends PropertyKey> =
|
|
47
|
+
DistributedOmit<Union, Key>;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Behavior and migration notes
|
|
51
|
+
|
|
52
|
+
- This rule only reports the narrow distributive-`Omit` helper pattern.
|
|
53
|
+
- It does not report ordinary `Omit<T, K>` usage.
|
|
54
|
+
- It does not try to prove that your generic key constraints match Type-Fest exactly; it only reports the direct structural helper pattern.
|
|
55
|
+
|
|
56
|
+
## ESLint flat config example
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import typefest from "eslint-plugin-typefest";
|
|
60
|
+
|
|
61
|
+
export default [typefest.configs.experimental];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## When not to use it
|
|
65
|
+
|
|
66
|
+
Disable this rule if your team prefers to keep a local distributive helper name or if you intentionally avoid Type-Fest for these object-union utilities.
|
|
67
|
+
|
|
68
|
+
## Package documentation
|
|
69
|
+
|
|
70
|
+
TypeFest package documentation:
|
|
71
|
+
|
|
72
|
+
Source file: [`source/distributed-omit.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/distributed-omit.d.ts)
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import type {DistributedOmit} from "type-fest";
|
|
76
|
+
|
|
77
|
+
type Result<Union, Key extends PropertyKey> = DistributedOmit<Union, Key>;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> **Rule catalog ID:** R090
|
|
81
|
+
|
|
82
|
+
## Further reading
|
|
83
|
+
|
|
84
|
+
- [`type-fest` README](https://github.com/sindresorhus/type-fest)
|
|
85
|
+
- [TypeScript Handbook: Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)
|
|
86
|
+
- [TypeScript Handbook: Omit](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys)
|
|
87
|
+
|
|
88
|
+
## Adoption resources
|
|
89
|
+
|
|
90
|
+
- [Rule adoption checklist](./guides/adoption-checklist.md)
|
|
91
|
+
- [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
|
|
92
|
+
- [Preset selection strategy](./guides/preset-selection-strategy.md)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# prefer-type-fest-distributed-pick
|
|
2
|
+
|
|
3
|
+
Prefer [`DistributedPick`](https://github.com/sindresorhus/type-fest/blob/main/source/distributed-pick.d.ts) from `type-fest` over distributive conditional helpers built from `Pick`.
|
|
4
|
+
|
|
5
|
+
This rule lives only in the experimental preset and reports without autofixing.
|
|
6
|
+
|
|
7
|
+
## Targeted pattern scope
|
|
8
|
+
|
|
9
|
+
This rule focuses on the common helper shape that distributes `Pick` over a union manually:
|
|
10
|
+
|
|
11
|
+
- `Union extends unknown ? Pick<Union, Key> : never`
|
|
12
|
+
- `Union extends any ? Pick<Union, Extract<Key, keyof Union>> : never`
|
|
13
|
+
|
|
14
|
+
It intentionally ignores ordinary non-distributive `Pick` usage and unrelated conditional helpers.
|
|
15
|
+
|
|
16
|
+
## What this rule reports
|
|
17
|
+
|
|
18
|
+
This rule reports conditional helpers when all of the following are true:
|
|
19
|
+
|
|
20
|
+
- the false branch is `never`
|
|
21
|
+
- the conditional distributes over the checked type with `extends unknown` or `extends any`
|
|
22
|
+
- the true branch is exactly `Pick<CheckedType, KeyType>` or `Pick<CheckedType, Extract<KeyType, keyof CheckedType>>`
|
|
23
|
+
|
|
24
|
+
The rule is currently **report-only**. It does not autofix or suggest a replacement yet.
|
|
25
|
+
|
|
26
|
+
## Why this rule exists
|
|
27
|
+
|
|
28
|
+
`DistributedPick<ObjectType, KeyType>` makes the union-preserving behavior explicit.
|
|
29
|
+
|
|
30
|
+
- The helper reads as a named concept instead of a conditional-type trick.
|
|
31
|
+
- It communicates why plain `Pick` is not enough for union-heavy object types.
|
|
32
|
+
- Standardizing on the upstream utility reduces local helper drift.
|
|
33
|
+
|
|
34
|
+
## ❌ Incorrect
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
type OnlyKeys<Union, Key extends PropertyKey> =
|
|
38
|
+
Union extends unknown ? Pick<Union, Key> : never;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## ✅ Correct
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import type {DistributedPick} from "type-fest";
|
|
45
|
+
|
|
46
|
+
type OnlyKeys<Union, Key extends PropertyKey> =
|
|
47
|
+
DistributedPick<Union, Key>;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Behavior and migration notes
|
|
51
|
+
|
|
52
|
+
- This rule only reports the narrow distributive-`Pick` helper pattern.
|
|
53
|
+
- It accepts the `Extract<Key, keyof Union>` variant because that is a common way to keep the built-in `Pick` constraint satisfied.
|
|
54
|
+
- It does not report plain `Pick<T, K>` usage.
|
|
55
|
+
|
|
56
|
+
## ESLint flat config example
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import typefest from "eslint-plugin-typefest";
|
|
60
|
+
|
|
61
|
+
export default [typefest.configs.experimental];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## When not to use it
|
|
65
|
+
|
|
66
|
+
Disable this rule if your project prefers a local helper name for distributive picking or if you intentionally avoid Type-Fest for object-union utilities.
|
|
67
|
+
|
|
68
|
+
## Package documentation
|
|
69
|
+
|
|
70
|
+
TypeFest package documentation:
|
|
71
|
+
|
|
72
|
+
Source file: [`source/distributed-pick.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/distributed-pick.d.ts)
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import type {DistributedPick} from "type-fest";
|
|
76
|
+
|
|
77
|
+
type Result<Union, Key extends PropertyKey> = DistributedPick<Union, Key>;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> **Rule catalog ID:** R091
|
|
81
|
+
|
|
82
|
+
## Further reading
|
|
83
|
+
|
|
84
|
+
- [`type-fest` README](https://github.com/sindresorhus/type-fest)
|
|
85
|
+
- [TypeScript Handbook: Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)
|
|
86
|
+
- [TypeScript Handbook: Pick](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)
|
|
87
|
+
|
|
88
|
+
## Adoption resources
|
|
89
|
+
|
|
90
|
+
- [Rule adoption checklist](./guides/adoption-checklist.md)
|
|
91
|
+
- [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
|
|
92
|
+
- [Preset selection strategy](./guides/preset-selection-strategy.md)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# prefer-type-fest-merge
|
|
2
|
+
|
|
3
|
+
Prefer [`Merge`](https://github.com/sindresorhus/type-fest/blob/main/source/merge.d.ts) from `type-fest` over `Except<Destination, keyof Source> & Source` intersections.
|
|
4
|
+
|
|
5
|
+
This rule lives only in the experimental preset and reports without autofixing.
|
|
6
|
+
|
|
7
|
+
## Targeted pattern scope
|
|
8
|
+
|
|
9
|
+
This rule focuses on direct merge-style intersections that already use `Except` from `type-fest` to remove overridden keys before intersecting with the overriding source type.
|
|
10
|
+
|
|
11
|
+
- `Except<Destination, keyof Source> & Source`
|
|
12
|
+
- `Source & Except<Destination, keyof Source>`
|
|
13
|
+
|
|
14
|
+
It intentionally skips builtin `Omit` forms and broader intersections to avoid overlapping with stable rules and to keep the report signal narrow.
|
|
15
|
+
|
|
16
|
+
## What this rule reports
|
|
17
|
+
|
|
18
|
+
This rule reports intersections when all of the following are true:
|
|
19
|
+
|
|
20
|
+
- one intersection member resolves to `Except`
|
|
21
|
+
- the second type argument to `Except` is exactly `keyof Source`
|
|
22
|
+
- the sibling intersection member is exactly `Source`
|
|
23
|
+
|
|
24
|
+
The rule is currently **report-only**. It does not autofix or suggest a replacement yet.
|
|
25
|
+
|
|
26
|
+
## Why this rule exists
|
|
27
|
+
|
|
28
|
+
`Merge<Destination, Source>` states the override relationship directly.
|
|
29
|
+
|
|
30
|
+
- Readers do not need to unpack an `Except`-plus-intersection recipe.
|
|
31
|
+
- The canonical helper signals that the second type wins on overlapping keys.
|
|
32
|
+
- The upstream utility also simplifies the resulting object type for tooling display.
|
|
33
|
+
|
|
34
|
+
## ❌ Incorrect
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import type {Except} from "type-fest";
|
|
38
|
+
|
|
39
|
+
type Base = {
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type Overrides = {
|
|
45
|
+
name: number;
|
|
46
|
+
readonly ok: true;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type Combined = Except<Base, keyof Overrides> & Overrides;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## ✅ Correct
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import type {Merge} from "type-fest";
|
|
56
|
+
|
|
57
|
+
type Base = {
|
|
58
|
+
id: string;
|
|
59
|
+
name: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
type Overrides = {
|
|
63
|
+
name: number;
|
|
64
|
+
readonly ok: true;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
type Combined = Merge<Base, Overrides>;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Behavior and migration notes
|
|
71
|
+
|
|
72
|
+
- This rule only reports the exact `Except<Destination, keyof Source> & Source` pattern.
|
|
73
|
+
- It ignores `Omit<Destination, keyof Source> & Source` so it does not double-report with `prefer-type-fest-except`.
|
|
74
|
+
- It ignores intersections whose sibling type does not match the `keyof` operand exactly.
|
|
75
|
+
|
|
76
|
+
## Additional examples
|
|
77
|
+
|
|
78
|
+
### ❌ Incorrect — Additional example
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import type {Except as StrictExcept} from "type-fest";
|
|
82
|
+
|
|
83
|
+
type Base = {
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
type Overrides = {
|
|
89
|
+
name: number;
|
|
90
|
+
readonly ok: true;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
type Combined = Overrides & StrictExcept<Base, keyof Overrides>;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### ✅ Correct — Additional example
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import type {Merge} from "type-fest";
|
|
100
|
+
|
|
101
|
+
type Base = {
|
|
102
|
+
id: string;
|
|
103
|
+
name: string;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
type Overrides = {
|
|
107
|
+
name: number;
|
|
108
|
+
readonly ok: true;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
type Combined = Merge<Base, Overrides>;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## ESLint flat config example
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import typefest from "eslint-plugin-typefest";
|
|
118
|
+
|
|
119
|
+
export default [typefest.configs.experimental];
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## When not to use it
|
|
123
|
+
|
|
124
|
+
Disable this rule if your team prefers the explicit `Except<..., keyof ...> & ...` construction, or if you want to keep the override mechanism visible in source types.
|
|
125
|
+
|
|
126
|
+
## Package documentation
|
|
127
|
+
|
|
128
|
+
TypeFest package documentation:
|
|
129
|
+
|
|
130
|
+
Source file: [`source/merge.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/merge.d.ts)
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import type {Merge} from "type-fest";
|
|
134
|
+
|
|
135
|
+
type Foo = {
|
|
136
|
+
a: string;
|
|
137
|
+
b: number;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
type Bar = {
|
|
141
|
+
a: number;
|
|
142
|
+
c: boolean;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
type FooBar = Merge<Foo, Bar>;
|
|
146
|
+
//=> {a: number; b: number; c: boolean}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
> **Rule catalog ID:** R088
|
|
150
|
+
|
|
151
|
+
## Further reading
|
|
152
|
+
|
|
153
|
+
- [`type-fest` README](https://github.com/sindresorhus/type-fest)
|
|
154
|
+
- [`type-fest` package reference](https://www.npmjs.com/package/type-fest)
|
|
155
|
+
- [TypeScript Handbook: Intersection Types](https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types)
|
|
156
|
+
|
|
157
|
+
## Adoption resources
|
|
158
|
+
|
|
159
|
+
- [Rule adoption checklist](./guides/adoption-checklist.md)
|
|
160
|
+
- [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
|
|
161
|
+
- [Preset selection strategy](./guides/preset-selection-strategy.md)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# prefer-type-fest-pick-index-signature
|
|
2
|
+
|
|
3
|
+
Prefer [`PickIndexSignature`](https://github.com/sindresorhus/type-fest/blob/main/source/pick-index-signature.d.ts) from `type-fest` over manual mapped types that keep only index signatures.
|
|
4
|
+
|
|
5
|
+
This rule lives only in the experimental preset and reports without autofixing.
|
|
6
|
+
|
|
7
|
+
## Targeted pattern scope
|
|
8
|
+
|
|
9
|
+
This rule focuses on the canonical mapped-type counterpart to `PickIndexSignature`:
|
|
10
|
+
|
|
11
|
+
- `{ [K in keyof T as {} extends Record<K, unknown> ? K : never]: T[K] }`
|
|
12
|
+
|
|
13
|
+
It intentionally skips the inverse `OmitIndexSignature` pattern and broader remapping logic.
|
|
14
|
+
|
|
15
|
+
## What this rule reports
|
|
16
|
+
|
|
17
|
+
This rule reports mapped types when all of the following are true:
|
|
18
|
+
|
|
19
|
+
- the key constraint is `keyof ObjectType`
|
|
20
|
+
- the key remap condition is `{} extends Record<Key, unknown> ? Key : never`
|
|
21
|
+
- the mapped value is `ObjectType[Key]`
|
|
22
|
+
|
|
23
|
+
The rule is currently **report-only**. It does not autofix or suggest a replacement yet.
|
|
24
|
+
|
|
25
|
+
## Why this rule exists
|
|
26
|
+
|
|
27
|
+
`PickIndexSignature<ObjectType>` names the intent directly.
|
|
28
|
+
|
|
29
|
+
- Readers do not need to decode the `Record<Key, unknown>` trick.
|
|
30
|
+
- The helper makes it obvious that only index signatures survive.
|
|
31
|
+
- Using the upstream utility keeps this niche pattern consistent across a codebase.
|
|
32
|
+
|
|
33
|
+
## ❌ Incorrect
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
type IndexOnly<ObjectType> = {
|
|
37
|
+
[Key in keyof ObjectType as {} extends Record<Key, unknown>
|
|
38
|
+
? Key
|
|
39
|
+
: never]: ObjectType[Key];
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## ✅ Correct
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import type {PickIndexSignature} from "type-fest";
|
|
47
|
+
|
|
48
|
+
type IndexOnly<ObjectType> = PickIndexSignature<ObjectType>;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Behavior and migration notes
|
|
52
|
+
|
|
53
|
+
- This rule only reports the narrow canonical mapped-type pattern.
|
|
54
|
+
- It intentionally ignores the inverse `{} extends Record<Key, unknown> ? never : Key` form because that belongs to `OmitIndexSignature`, not `PickIndexSignature`.
|
|
55
|
+
- It also ignores broader remapped types that do more than keep index signatures.
|
|
56
|
+
|
|
57
|
+
## ESLint flat config example
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import typefest from "eslint-plugin-typefest";
|
|
61
|
+
|
|
62
|
+
export default [typefest.configs.experimental];
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## When not to use it
|
|
66
|
+
|
|
67
|
+
Disable this rule if your team prefers the explicit mapped type or if you want to reserve `PickIndexSignature` for only a subset of object utility code.
|
|
68
|
+
|
|
69
|
+
## Package documentation
|
|
70
|
+
|
|
71
|
+
TypeFest package documentation:
|
|
72
|
+
|
|
73
|
+
Source file: [`source/pick-index-signature.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/pick-index-signature.d.ts)
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import type {PickIndexSignature} from "type-fest";
|
|
77
|
+
|
|
78
|
+
type IndexOnly<ObjectType> = PickIndexSignature<ObjectType>;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **Rule catalog ID:** R094
|
|
82
|
+
|
|
83
|
+
## Further reading
|
|
84
|
+
|
|
85
|
+
- [`type-fest` README](https://github.com/sindresorhus/type-fest)
|
|
86
|
+
- [TypeScript Handbook: Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)
|
|
87
|
+
- [TypeScript Handbook: keyof](https://www.typescriptlang.org/docs/handbook/2/keyof-types.html)
|
|
88
|
+
|
|
89
|
+
## Adoption resources
|
|
90
|
+
|
|
91
|
+
- [Rule adoption checklist](./guides/adoption-checklist.md)
|
|
92
|
+
- [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
|
|
93
|
+
- [Preset selection strategy](./guides/preset-selection-strategy.md)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# prefer-type-fest-set-return-type
|
|
2
|
+
|
|
3
|
+
Prefer [`SetReturnType`](https://github.com/sindresorhus/type-fest/blob/main/source/set-return-type.d.ts) from `type-fest` over direct function-type wrappers built from `Parameters`.
|
|
4
|
+
|
|
5
|
+
This rule lives only in the experimental preset and reports without autofixing.
|
|
6
|
+
|
|
7
|
+
## Targeted pattern scope
|
|
8
|
+
|
|
9
|
+
This rule focuses on direct function-type wrappers of the form:
|
|
10
|
+
|
|
11
|
+
- `(...args: Parameters<Function>) => Result`
|
|
12
|
+
|
|
13
|
+
It intentionally skips the async-specific `Promise<Awaited<ReturnType<Function>>>` shape so the more specific `prefer-type-fest-asyncify` rule can handle that case.
|
|
14
|
+
|
|
15
|
+
## What this rule reports
|
|
16
|
+
|
|
17
|
+
This rule reports function types when all of the following are true:
|
|
18
|
+
|
|
19
|
+
- the function type has exactly one rest parameter
|
|
20
|
+
- that rest parameter is typed as `Parameters<Function>`
|
|
21
|
+
- the return type is not the original `ReturnType<Function>`
|
|
22
|
+
- the return type is not the `Asyncify` shape `Promise<Awaited<ReturnType<Function>>>`
|
|
23
|
+
|
|
24
|
+
The rule is currently **report-only**. It does not autofix or suggest a replacement yet.
|
|
25
|
+
|
|
26
|
+
## Why this rule exists
|
|
27
|
+
|
|
28
|
+
`SetReturnType<Function, Result>` states the transformation directly.
|
|
29
|
+
|
|
30
|
+
- Readers can see that only the return type changes.
|
|
31
|
+
- The helper is easier to reuse consistently across wrapper types.
|
|
32
|
+
- It avoids repeating the same `Parameters<...>` boilerplate in local helper types.
|
|
33
|
+
|
|
34
|
+
## ❌ Incorrect
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
type WithResult<Function_ extends (...arguments_: any[]) => any, Result> =
|
|
38
|
+
(...arguments_: Parameters<Function_>) => Result;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## ✅ Correct
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import type {SetReturnType} from "type-fest";
|
|
45
|
+
|
|
46
|
+
type WithResult<Function_ extends (...arguments_: any[]) => any, Result> =
|
|
47
|
+
SetReturnType<Function_, Result>;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Behavior and migration notes
|
|
51
|
+
|
|
52
|
+
- This rule targets the narrow rest-parameter form `(...args: Parameters<F>) => R`.
|
|
53
|
+
- It ignores ordinary handwritten function types with explicit parameters.
|
|
54
|
+
- It intentionally defers asyncified wrappers to `prefer-type-fest-asyncify`.
|
|
55
|
+
|
|
56
|
+
## ESLint flat config example
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import typefest from "eslint-plugin-typefest";
|
|
60
|
+
|
|
61
|
+
export default [typefest.configs.experimental];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## When not to use it
|
|
65
|
+
|
|
66
|
+
Disable this rule if your team prefers to spell out the wrapper function type explicitly or if you need a custom helper name for return-type rewrites.
|
|
67
|
+
|
|
68
|
+
## Package documentation
|
|
69
|
+
|
|
70
|
+
TypeFest package documentation:
|
|
71
|
+
|
|
72
|
+
Source file: [`source/set-return-type.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/set-return-type.d.ts)
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import type {SetReturnType} from "type-fest";
|
|
76
|
+
|
|
77
|
+
type Wrapped<Function_ extends (...arguments_: any[]) => any> =
|
|
78
|
+
SetReturnType<Function_, string>;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **Rule catalog ID:** R092
|
|
82
|
+
|
|
83
|
+
## Further reading
|
|
84
|
+
|
|
85
|
+
- [`type-fest` README](https://github.com/sindresorhus/type-fest)
|
|
86
|
+
- [TypeScript Handbook: Parameters](https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype)
|
|
87
|
+
- [TypeScript Handbook: ReturnType](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype)
|
|
88
|
+
|
|
89
|
+
## Adoption resources
|
|
90
|
+
|
|
91
|
+
- [Rule adoption checklist](./guides/adoption-checklist.md)
|
|
92
|
+
- [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
|
|
93
|
+
- [Preset selection strategy](./guides/preset-selection-strategy.md)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# prefer-type-fest-stringified
|
|
2
|
+
|
|
3
|
+
Prefer [`Stringified`](https://github.com/sindresorhus/type-fest/blob/main/source/stringified.d.ts) from `type-fest` over manual mapped types of the form `{ [K in keyof T]: string }`.
|
|
4
|
+
|
|
5
|
+
This rule lives only in the experimental preset and reports without autofixing.
|
|
6
|
+
|
|
7
|
+
## Targeted pattern scope
|
|
8
|
+
|
|
9
|
+
This rule focuses on direct mapped types that convert every property value in a source object type to `string`.
|
|
10
|
+
|
|
11
|
+
- `{ [Key in keyof T]: string }`
|
|
12
|
+
|
|
13
|
+
It intentionally skips mapped types with readonly modifiers, optional modifiers, key remapping, or non-string value expressions.
|
|
14
|
+
|
|
15
|
+
## What this rule reports
|
|
16
|
+
|
|
17
|
+
This rule reports mapped types when all of the following are true:
|
|
18
|
+
|
|
19
|
+
- the key constraint is exactly `keyof T`
|
|
20
|
+
- the mapped value type is exactly `string`
|
|
21
|
+
- there is no key remapping
|
|
22
|
+
- there are no readonly or optional mapped modifiers
|
|
23
|
+
|
|
24
|
+
The rule is currently **report-only**. It does not autofix or suggest a replacement yet.
|
|
25
|
+
|
|
26
|
+
## Why this rule exists
|
|
27
|
+
|
|
28
|
+
`Stringified<T>` names the transformation directly.
|
|
29
|
+
|
|
30
|
+
- The helper is shorter than repeating the mapped-type recipe inline.
|
|
31
|
+
- The intent is easier to recognize in form models and serialization layers.
|
|
32
|
+
- The shared utility keeps the codebase consistent when the same transformation appears in multiple places.
|
|
33
|
+
|
|
34
|
+
## ❌ Incorrect
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
type Car = {
|
|
38
|
+
model: string;
|
|
39
|
+
speed: number;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type CarForm = { [Key in keyof Car]: string };
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## ✅ Correct
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import type {Stringified} from "type-fest";
|
|
49
|
+
|
|
50
|
+
type Car = {
|
|
51
|
+
model: string;
|
|
52
|
+
speed: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type CarForm = Stringified<Car>;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Behavior and migration notes
|
|
59
|
+
|
|
60
|
+
- This rule only reports the exact mapped-type shape `{ [Key in keyof T]: string }`.
|
|
61
|
+
- It ignores mapped types that also change key names or property modifiers.
|
|
62
|
+
- It ignores mapped types whose value side is not exactly `string`.
|
|
63
|
+
|
|
64
|
+
## Additional examples
|
|
65
|
+
|
|
66
|
+
### ❌ Incorrect — Additional example
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
type Payload = {
|
|
70
|
+
attemptCount: number;
|
|
71
|
+
success: boolean;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
type PayloadForm = { [Key in keyof Payload]: string };
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### ✅ Correct — Additional example
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import type {Stringified} from "type-fest";
|
|
81
|
+
|
|
82
|
+
type Payload = {
|
|
83
|
+
attemptCount: number;
|
|
84
|
+
success: boolean;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
type PayloadForm = Stringified<Payload>;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## ESLint flat config example
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import typefest from "eslint-plugin-typefest";
|
|
94
|
+
|
|
95
|
+
export default [typefest.configs.experimental];
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## When not to use it
|
|
99
|
+
|
|
100
|
+
Disable this rule if your team prefers inline mapped types for one-off transformations, or if the mapped type needs to evolve beyond the exact `Stringified<T>` shape.
|
|
101
|
+
|
|
102
|
+
## Package documentation
|
|
103
|
+
|
|
104
|
+
TypeFest package documentation:
|
|
105
|
+
|
|
106
|
+
Source file: [`source/stringified.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/stringified.d.ts)
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import type {Stringified} from "type-fest";
|
|
110
|
+
|
|
111
|
+
type Car = {
|
|
112
|
+
model: string;
|
|
113
|
+
speed: number;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const carForm: Stringified<Car> = {
|
|
117
|
+
model: "Foo",
|
|
118
|
+
speed: "101",
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
> **Rule catalog ID:** R089
|
|
123
|
+
|
|
124
|
+
## Further reading
|
|
125
|
+
|
|
126
|
+
- [`type-fest` README](https://github.com/sindresorhus/type-fest)
|
|
127
|
+
- [`type-fest` package reference](https://www.npmjs.com/package/type-fest)
|
|
128
|
+
- [TypeScript Handbook: Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)
|
|
129
|
+
|
|
130
|
+
## Adoption resources
|
|
131
|
+
|
|
132
|
+
- [Rule adoption checklist](./guides/adoption-checklist.md)
|
|
133
|
+
- [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
|
|
134
|
+
- [Preset selection strategy](./guides/preset-selection-strategy.md)
|