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.
Files changed (92) hide show
  1. package/README.md +19 -3
  2. package/dist/_internal/constrained-type-at-location.d.ts.map +1 -1
  3. package/dist/_internal/constrained-type-at-location.js.map +1 -1
  4. package/dist/_internal/function-type-reference-patterns.d.ts +34 -0
  5. package/dist/_internal/function-type-reference-patterns.d.ts.map +1 -0
  6. package/dist/_internal/function-type-reference-patterns.js +103 -0
  7. package/dist/_internal/function-type-reference-patterns.js.map +1 -0
  8. package/dist/_internal/rule-catalog.d.ts.map +1 -1
  9. package/dist/_internal/rule-catalog.js +11 -0
  10. package/dist/_internal/rule-catalog.js.map +1 -1
  11. package/dist/_internal/rules-registry.d.ts.map +1 -1
  12. package/dist/_internal/rules-registry.js +22 -0
  13. package/dist/_internal/rules-registry.js.map +1 -1
  14. package/dist/_internal/set-membership.d.ts.map +1 -1
  15. package/dist/_internal/set-membership.js.map +1 -1
  16. package/dist/_internal/type-checker-compat.d.ts.map +1 -1
  17. package/dist/_internal/type-checker-compat.js.map +1 -1
  18. package/dist/_internal/type-reference-node.d.ts +8 -0
  19. package/dist/_internal/type-reference-node.d.ts.map +1 -1
  20. package/dist/_internal/type-reference-node.js +14 -0
  21. package/dist/_internal/type-reference-node.js.map +1 -1
  22. package/dist/_internal/typefest-config-references.d.ts +2 -1
  23. package/dist/_internal/typefest-config-references.d.ts.map +1 -1
  24. package/dist/_internal/typefest-config-references.js +11 -2
  25. package/dist/_internal/typefest-config-references.js.map +1 -1
  26. package/dist/_internal/typescript-eslint-node-autofix.js.map +1 -1
  27. package/dist/plugin.cjs +1069 -117
  28. package/dist/plugin.cjs.map +4 -4
  29. package/dist/plugin.d.ts.map +1 -1
  30. package/dist/plugin.js +5 -0
  31. package/dist/plugin.js.map +1 -1
  32. package/dist/rules/prefer-ts-extras-object-map-values.d.ts +14 -0
  33. package/dist/rules/prefer-ts-extras-object-map-values.d.ts.map +1 -0
  34. package/dist/rules/prefer-ts-extras-object-map-values.js +227 -0
  35. package/dist/rules/prefer-ts-extras-object-map-values.js.map +1 -0
  36. package/dist/rules/prefer-type-fest-asyncify.d.ts +7 -0
  37. package/dist/rules/prefer-type-fest-asyncify.d.ts.map +1 -0
  38. package/dist/rules/prefer-type-fest-asyncify.js +79 -0
  39. package/dist/rules/prefer-type-fest-asyncify.js.map +1 -0
  40. package/dist/rules/prefer-type-fest-conditional-except.d.ts +7 -0
  41. package/dist/rules/prefer-type-fest-conditional-except.d.ts.map +1 -0
  42. package/dist/rules/prefer-type-fest-conditional-except.js +94 -0
  43. package/dist/rules/prefer-type-fest-conditional-except.js.map +1 -0
  44. package/dist/rules/prefer-type-fest-conditional-keys.d.ts +7 -0
  45. package/dist/rules/prefer-type-fest-conditional-keys.d.ts.map +1 -0
  46. package/dist/rules/prefer-type-fest-conditional-keys.js +78 -0
  47. package/dist/rules/prefer-type-fest-conditional-keys.js.map +1 -0
  48. package/dist/rules/prefer-type-fest-distributed-omit.d.ts +7 -0
  49. package/dist/rules/prefer-type-fest-distributed-omit.d.ts.map +1 -0
  50. package/dist/rules/prefer-type-fest-distributed-omit.js +67 -0
  51. package/dist/rules/prefer-type-fest-distributed-omit.js.map +1 -0
  52. package/dist/rules/prefer-type-fest-distributed-pick.d.ts +7 -0
  53. package/dist/rules/prefer-type-fest-distributed-pick.d.ts.map +1 -0
  54. package/dist/rules/prefer-type-fest-distributed-pick.js +95 -0
  55. package/dist/rules/prefer-type-fest-distributed-pick.js.map +1 -0
  56. package/dist/rules/prefer-type-fest-merge.d.ts +7 -0
  57. package/dist/rules/prefer-type-fest-merge.d.ts.map +1 -0
  58. package/dist/rules/prefer-type-fest-merge.js +93 -0
  59. package/dist/rules/prefer-type-fest-merge.js.map +1 -0
  60. package/dist/rules/prefer-type-fest-pick-index-signature.d.ts +7 -0
  61. package/dist/rules/prefer-type-fest-pick-index-signature.d.ts.map +1 -0
  62. package/dist/rules/prefer-type-fest-pick-index-signature.js +98 -0
  63. package/dist/rules/prefer-type-fest-pick-index-signature.js.map +1 -0
  64. package/dist/rules/prefer-type-fest-set-return-type.d.ts +7 -0
  65. package/dist/rules/prefer-type-fest-set-return-type.d.ts.map +1 -0
  66. package/dist/rules/prefer-type-fest-set-return-type.js +53 -0
  67. package/dist/rules/prefer-type-fest-set-return-type.js.map +1 -0
  68. package/dist/rules/prefer-type-fest-stringified.d.ts +7 -0
  69. package/dist/rules/prefer-type-fest-stringified.d.ts.map +1 -0
  70. package/dist/rules/prefer-type-fest-stringified.js +73 -0
  71. package/dist/rules/prefer-type-fest-stringified.js.map +1 -0
  72. package/dist/rules/prefer-type-fest-union-to-intersection.d.ts +7 -0
  73. package/dist/rules/prefer-type-fest-union-to-intersection.d.ts.map +1 -0
  74. package/dist/rules/prefer-type-fest-union-to-intersection.js +114 -0
  75. package/dist/rules/prefer-type-fest-union-to-intersection.js.map +1 -0
  76. package/docs/rules/getting-started.md +2 -1
  77. package/docs/rules/guides/preset-selection-strategy.md +7 -0
  78. package/docs/rules/overview.md +1 -0
  79. package/docs/rules/prefer-ts-extras-object-map-values.md +146 -0
  80. package/docs/rules/prefer-type-fest-asyncify.md +93 -0
  81. package/docs/rules/prefer-type-fest-conditional-except.md +141 -0
  82. package/docs/rules/prefer-type-fest-conditional-keys.md +93 -0
  83. package/docs/rules/prefer-type-fest-distributed-omit.md +92 -0
  84. package/docs/rules/prefer-type-fest-distributed-pick.md +92 -0
  85. package/docs/rules/prefer-type-fest-merge.md +161 -0
  86. package/docs/rules/prefer-type-fest-pick-index-signature.md +93 -0
  87. package/docs/rules/prefer-type-fest-set-return-type.md +93 -0
  88. package/docs/rules/prefer-type-fest-stringified.md +134 -0
  89. package/docs/rules/prefer-type-fest-union-to-intersection.md +118 -0
  90. package/docs/rules/presets/experimental.md +163 -0
  91. package/docs/rules/presets/index.md +13 -0
  92. 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)