eslint-plugin-typefest 1.2.1 → 1.2.3

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 (49) hide show
  1. package/README.md +6 -0
  2. package/dist/_internal/rule-catalog.d.ts.map +1 -1
  3. package/dist/_internal/rule-catalog.js +6 -0
  4. package/dist/_internal/rule-catalog.js.map +1 -1
  5. package/dist/_internal/rules-registry.d.ts.map +1 -1
  6. package/dist/_internal/rules-registry.js +12 -0
  7. package/dist/_internal/rules-registry.js.map +1 -1
  8. package/dist/plugin.cjs +486 -52
  9. package/dist/plugin.cjs.map +4 -4
  10. package/dist/rules/prefer-ts-extras-assert-never.d.ts +13 -0
  11. package/dist/rules/prefer-ts-extras-assert-never.d.ts.map +1 -0
  12. package/dist/rules/prefer-ts-extras-assert-never.js +116 -0
  13. package/dist/rules/prefer-ts-extras-assert-never.js.map +1 -0
  14. package/dist/rules/prefer-ts-extras-is-property-defined.d.ts +13 -0
  15. package/dist/rules/prefer-ts-extras-is-property-defined.d.ts.map +1 -0
  16. package/dist/rules/prefer-ts-extras-is-property-defined.js +160 -0
  17. package/dist/rules/prefer-ts-extras-is-property-defined.js.map +1 -0
  18. package/dist/rules/prefer-ts-extras-is-property-present.d.ts +13 -0
  19. package/dist/rules/prefer-ts-extras-is-property-present.d.ts.map +1 -0
  20. package/dist/rules/prefer-ts-extras-is-property-present.js +114 -0
  21. package/dist/rules/prefer-ts-extras-is-property-present.js.map +1 -0
  22. package/dist/rules/prefer-type-fest-absolute.d.ts +13 -0
  23. package/dist/rules/prefer-type-fest-absolute.d.ts.map +1 -0
  24. package/dist/rules/prefer-type-fest-absolute.js +67 -0
  25. package/dist/rules/prefer-type-fest-absolute.js.map +1 -0
  26. package/dist/rules/prefer-type-fest-non-nullable-deep.d.ts +13 -0
  27. package/dist/rules/prefer-type-fest-non-nullable-deep.d.ts.map +1 -0
  28. package/dist/rules/prefer-type-fest-non-nullable-deep.js +58 -0
  29. package/dist/rules/prefer-type-fest-non-nullable-deep.js.map +1 -0
  30. package/dist/rules/prefer-type-fest-union-length.d.ts +13 -0
  31. package/dist/rules/prefer-type-fest-union-length.d.ts.map +1 -0
  32. package/dist/rules/prefer-type-fest-union-length.js +75 -0
  33. package/dist/rules/prefer-type-fest-union-length.js.map +1 -0
  34. package/docs/rules/prefer-ts-extras-assert-never.md +112 -0
  35. package/docs/rules/prefer-ts-extras-is-property-defined.md +119 -0
  36. package/docs/rules/prefer-ts-extras-is-property-present.md +118 -0
  37. package/docs/rules/prefer-type-fest-absolute.md +99 -0
  38. package/docs/rules/prefer-type-fest-non-nullable-deep.md +105 -0
  39. package/docs/rules/prefer-type-fest-union-length.md +100 -0
  40. package/docs/rules/presets/all.md +6 -0
  41. package/docs/rules/presets/experimental.md +6 -0
  42. package/docs/rules/presets/index.md +6 -0
  43. package/docs/rules/presets/minimal.md +2 -0
  44. package/docs/rules/presets/recommended-type-checked.md +6 -0
  45. package/docs/rules/presets/recommended.md +6 -0
  46. package/docs/rules/presets/strict.md +6 -0
  47. package/docs/rules/presets/ts-extras-type-guards.md +3 -0
  48. package/docs/rules/presets/type-fest-types.md +3 -0
  49. package/package.json +24 -20
@@ -0,0 +1,13 @@
1
+ import { createTypedRule } from "../_internal/typed-rule.js";
2
+ /**
3
+ * ESLint rule definition for `prefer-type-fest-union-length`.
4
+ *
5
+ * @remarks
6
+ * Defines metadata, diagnostics, and suggestions/fixes for this rule.
7
+ */
8
+ declare const preferTypeFestUnionLengthRule: ReturnType<typeof createTypedRule>;
9
+ /**
10
+ * Default export for the `prefer-type-fest-union-length` rule module.
11
+ */
12
+ export default preferTypeFestUnionLengthRule;
13
+ //# sourceMappingURL=prefer-type-fest-union-length.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-type-fest-union-length.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-type-fest-union-length.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;;;GAKG;AACH,QAAA,MAAM,6BAA6B,EAAE,UAAU,CAAC,OAAO,eAAe,CAoFhE,CAAC;AAEP;;GAEG;AACH,eAAe,6BAA6B,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { arrayFirst } from "ts-extras";
2
+ import { collectDirectNamedImportsFromSource, createSafeTypeNodeTextReplacementFix, } from "../_internal/imported-type-aliases.js";
3
+ import { TYPE_FEST_MODULE_SOURCE } from "../_internal/module-source.js";
4
+ import { reportWithOptionalFix } from "../_internal/rule-reporting.js";
5
+ import { createTypedRule } from "../_internal/typed-rule.js";
6
+ /**
7
+ * ESLint rule definition for `prefer-type-fest-union-length`.
8
+ *
9
+ * @remarks
10
+ * Defines metadata, diagnostics, and suggestions/fixes for this rule.
11
+ */
12
+ const preferTypeFestUnionLengthRule = createTypedRule({
13
+ create(context) {
14
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
15
+ return {
16
+ TSIndexedAccessType(node) {
17
+ const { indexType, objectType } = node;
18
+ // Require: objectType is TSTypeReference named "UnionToTuple"
19
+ if (objectType.type !== "TSTypeReference" ||
20
+ objectType.typeName.type !== "Identifier" ||
21
+ objectType.typeName.name !== "UnionToTuple") {
22
+ return;
23
+ }
24
+ // Require: indexType is TSLiteralType with string literal "length"
25
+ if (indexType.type !== "TSLiteralType" ||
26
+ indexType.literal.type !== "Literal" ||
27
+ indexType.literal.value !== "length") {
28
+ return;
29
+ }
30
+ // Require: UnionToTuple has exactly one type argument to forward
31
+ const typeParams = objectType.typeArguments?.params;
32
+ if (typeParams?.length !== 1) {
33
+ return;
34
+ }
35
+ const typeArgText = context.sourceCode.getText(arrayFirst(typeParams));
36
+ const replacementText = `UnionLength<${typeArgText}>`;
37
+ const replacementFix = createSafeTypeNodeTextReplacementFix(node, "UnionLength", replacementText, typeFestDirectImports);
38
+ reportWithOptionalFix({
39
+ context,
40
+ fix: replacementFix,
41
+ messageId: "preferUnionLength",
42
+ node,
43
+ });
44
+ },
45
+ };
46
+ },
47
+ meta: {
48
+ deprecated: false,
49
+ docs: {
50
+ description: "require TypeFest `UnionLength` over `UnionToTuple<T>['length']`.",
51
+ frozen: false,
52
+ recommended: true,
53
+ requiresTypeChecking: false,
54
+ typefestConfigs: [
55
+ "typefest.configs.recommended",
56
+ "typefest.configs.strict",
57
+ "typefest.configs.all",
58
+ "typefest.configs.type-fest/types",
59
+ ],
60
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-union-length",
61
+ },
62
+ fixable: "code",
63
+ messages: {
64
+ preferUnionLength: "Prefer `UnionLength<T>` from type-fest over `UnionToTuple<T>['length']`.",
65
+ },
66
+ schema: [],
67
+ type: "suggestion",
68
+ },
69
+ name: "prefer-type-fest-union-length",
70
+ });
71
+ /**
72
+ * Default export for the `prefer-type-fest-union-length` rule module.
73
+ */
74
+ export default preferTypeFestUnionLengthRule;
75
+ //# sourceMappingURL=prefer-type-fest-union-length.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-type-fest-union-length.js","sourceRoot":"","sources":["../../src/rules/prefer-type-fest-union-length.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EACH,mCAAmC,EACnC,oCAAoC,GACvC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,6BAA6B,GAC/B,eAAe,CAAC;IACZ,MAAM,CAAC,OAAO;QACV,MAAM,qBAAqB,GAAG,mCAAmC,CAC7D,OAAO,CAAC,UAAU,EAClB,uBAAuB,CAC1B,CAAC;QAEF,OAAO;YACH,mBAAmB,CACf,IAA4C;gBAE5C,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;gBAEvC,8DAA8D;gBAC9D,IACI,UAAU,CAAC,IAAI,KAAK,iBAAiB;oBACrC,UAAU,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;oBACzC,UAAU,CAAC,QAAQ,CAAC,IAAI,KAAK,cAAc,EAC7C,CAAC;oBACC,OAAO;gBACX,CAAC;gBAED,mEAAmE;gBACnE,IACI,SAAS,CAAC,IAAI,KAAK,eAAe;oBAClC,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS;oBACpC,SAAS,CAAC,OAAO,CAAC,KAAK,KAAK,QAAQ,EACtC,CAAC;oBACC,OAAO;gBACX,CAAC;gBAED,iEAAiE;gBACjE,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,EAAE,MAAM,CAAC;gBACpD,IAAI,UAAU,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC3B,OAAO;gBACX,CAAC;gBAED,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAC1C,UAAU,CAAC,UAAU,CAAkB,CAC1C,CAAC;gBACF,MAAM,eAAe,GAAG,eAAe,WAAW,GAAG,CAAC;gBAEtD,MAAM,cAAc,GAAG,oCAAoC,CACvD,IAAI,EACJ,aAAa,EACb,eAAe,EACf,qBAAqB,CACxB,CAAC;gBAEF,qBAAqB,CAAC;oBAClB,OAAO;oBACP,GAAG,EAAE,cAAc;oBACnB,SAAS,EAAE,mBAAmB;oBAC9B,IAAI;iBACP,CAAC,CAAC;YACP,CAAC;SACJ,CAAC;IACN,CAAC;IACD,IAAI,EAAE;QACF,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE;YACF,WAAW,EACP,kEAAkE;YACtE,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,IAAI;YACjB,oBAAoB,EAAE,KAAK;YAC3B,eAAe,EAAE;gBACb,8BAA8B;gBAC9B,yBAAyB;gBACzB,sBAAsB;gBACtB,kCAAkC;aACrC;YACD,GAAG,EAAE,8FAA8F;SACtG;QACD,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE;YACN,iBAAiB,EACb,0EAA0E;SACjF;QACD,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,YAAY;KACrB;IACD,IAAI,EAAE,+BAA+B;CACxC,CAAC,CAAC;AAEP;;GAEG;AACH,eAAe,6BAA6B,CAAC"}
@@ -0,0 +1,112 @@
1
+ # prefer-ts-extras-assert-never
2
+
3
+ Require [`assertNever`](https://github.com/sindresorhus/ts-extras/blob/main/source/assert-never.ts) from `ts-extras` over manual `const _: never = value` exhaustiveness checks.
4
+
5
+ ## Targeted pattern scope
6
+
7
+ This rule only inspects single-declarator `const` statements where the declared identifier has a `never` type annotation.
8
+
9
+ - `const _exhaustiveCheck: never = value;`
10
+ - `const _: never = someExpression;`
11
+
12
+ Named function calls, `throw` statements, and other exhaustiveness patterns are not matched.
13
+
14
+ ## What this rule reports
15
+
16
+ This rule reports `const` declarations where the declared identifier is explicitly annotated with `never`, indicating a manual exhaustiveness check that can be replaced with `assertNever`.
17
+
18
+ - Single-declarator `const` statements with a `never` type annotation.
19
+
20
+ ## Why this rule exists
21
+
22
+ `assertNever(value)` is the canonical `ts-extras` utility for exhaustive-switch and discriminated-union coverage checks.
23
+
24
+ - It is an explicit, searchable name for exhaustiveness enforcement.
25
+ - It throws at runtime with a descriptive message if an unexpected value is encountered, unlike a silent `const _: never` declaration.
26
+ - Standardizing the pattern ensures consistent behavior across the codebase — the silent-assignment form compiles away and provides no runtime safety.
27
+
28
+ ## ❌ Incorrect
29
+
30
+ ```ts
31
+ const _exhaustiveCheck: never = fruit;
32
+ ```
33
+
34
+ ## ✅ Correct
35
+
36
+ ```ts
37
+ import { assertNever } from "ts-extras";
38
+
39
+ assertNever(fruit);
40
+ ```
41
+
42
+ ## Behavior and migration notes
43
+
44
+ - `assertNever(value)` throws at runtime when called with a value. The manual `const _: never = value` pattern is a compile-time-only check that is silently removed after transpilation.
45
+ - Applying the suggestion changes runtime semantics: unreachable branches will throw instead of silently passing. Verify the code path is truly unreachable before applying.
46
+ - The rule provides a **suggestion** (not an autofix) because the runtime-behavior change must be reviewed manually.
47
+ - Multi-declarator `const` statements (e.g., `const _a: never = a, _b: never = b`) are intentionally excluded.
48
+
49
+ ## ESLint flat config example
50
+
51
+ ```ts
52
+ import typefest from "eslint-plugin-typefest";
53
+
54
+ export default [
55
+ {
56
+ plugins: { typefest },
57
+ rules: {
58
+ "typefest/prefer-ts-extras-assert-never": "warn",
59
+ },
60
+ },
61
+ ];
62
+ ```
63
+
64
+ ## When not to use it
65
+
66
+ Disable this rule if your codebase deliberately uses the `const _: never` pattern to avoid introducing runtime-throwing behavior in unreachable branches.
67
+
68
+ ## Package documentation
69
+
70
+ ts-extras package documentation:
71
+
72
+ Source file: [`source/assert-never.ts`](https://github.com/sindresorhus/ts-extras/blob/main/source/assert-never.ts)
73
+
74
+ ````ts
75
+ /**
76
+ Assert that the given value is `never`.
77
+
78
+ This is useful to ensure that a `switch` statement or `if`-`else` chain is exhaustive — meaning that all possible cases are handled.
79
+
80
+ An `assertNever` call is a compile-time type-check and will throw at runtime if the given value is not `never`.
81
+
82
+ @example
83
+ ```
84
+ import {assertNever} from 'ts-extras';
85
+
86
+ type Fruit = 'apple' | 'banana' | 'cherry';
87
+
88
+ function isYellow(fruit: Fruit): boolean {
89
+ switch (fruit) {
90
+ case 'apple':
91
+ return false;
92
+ case 'banana':
93
+ return true;
94
+ case 'cherry':
95
+ return false;
96
+ default:
97
+ assertNever(fruit);
98
+ }
99
+ }
100
+ ```
101
+
102
+ @category Type guard
103
+ */
104
+ ````
105
+
106
+ > **Rule catalog ID:** R100
107
+
108
+ ## Further reading
109
+
110
+ - [`ts-extras` README](https://github.com/sindresorhus/ts-extras)
111
+ - [`ts-extras` package reference](https://www.npmjs.com/package/ts-extras)
112
+ - [TypeScript Handbook: Narrowing](https://www.typescriptlang.org/docs/handbook/2/narrowing.html)
@@ -0,0 +1,119 @@
1
+ # prefer-ts-extras-is-property-defined
2
+
3
+ Require [`isPropertyDefined`](https://github.com/sindresorhus/ts-extras/blob/main/source/is-property-defined.ts) from `ts-extras` in `Array.prototype.filter` callbacks instead of inline property-undefined checks.
4
+
5
+ ## Targeted pattern scope
6
+
7
+ This rule only inspects inline `.filter(...)` predicates that perform an explicit `undefined` check against a single object property.
8
+
9
+ - Inline property-undefined predicates inside `.filter(...)`, including:
10
+ - `filter((item) => item.prop !== undefined)`
11
+ - `filter((item) => undefined !== item.prop)`
12
+ - `filter((item) => item.prop != undefined)`
13
+ - `filter((item) => typeof item.prop !== "undefined")`
14
+
15
+ Named predicate references, multi-argument callbacks, and broader callback logic are not matched unless they preserve this property-undefined-check shape.
16
+
17
+ ## What this rule reports
18
+
19
+ This rule reports inline filter predicates that check whether a single object property is not `undefined` and can be normalized with `isPropertyDefined`.
20
+
21
+ ## Why this rule exists
22
+
23
+ `filter(isPropertyDefined('prop'))` is the canonical `ts-extras` pattern for filtering out items where a specific property is `undefined`.
24
+
25
+ - Filtering logic is consistent and composable across collections.
26
+ - The property key is explicit in the function call, not hidden inside a callback.
27
+ - Repeated inline `!== undefined` callback expressions are removed.
28
+ - `isPropertyDefined` is a proper type predicate that narrows element types in the resulting array.
29
+
30
+ ## ❌ Incorrect
31
+
32
+ ```ts
33
+ const named = users.filter((user) => user.name !== undefined);
34
+ ```
35
+
36
+ ## ✅ Correct
37
+
38
+ ```ts
39
+ import { isPropertyDefined } from "ts-extras";
40
+
41
+ const named = users.filter(isPropertyDefined("name"));
42
+ ```
43
+
44
+ ## Behavior and migration notes
45
+
46
+ - `isPropertyDefined('prop')` checks `item[prop] !== undefined` and narrows the result type accordingly.
47
+ - The autofix preserves the property name as a string literal.
48
+ - Deep property access (e.g., `user.address.street !== undefined`) is intentionally excluded — only single-level property checks are flagged.
49
+ - Computed property access (e.g., `user[key] !== undefined`) is intentionally excluded.
50
+
51
+ ## Additional examples
52
+
53
+ ### ❌ Incorrect — typeof form
54
+
55
+ ```ts
56
+ const named = users.filter((user) => typeof user.name !== "undefined");
57
+ ```
58
+
59
+ ### ✅ Correct — typeof form fixed
60
+
61
+ ```ts
62
+ const named = users.filter(isPropertyDefined("name"));
63
+ ```
64
+
65
+ ## ESLint flat config example
66
+
67
+ ```ts
68
+ import typefest from "eslint-plugin-typefest";
69
+
70
+ export default [
71
+ {
72
+ plugins: { typefest },
73
+ rules: {
74
+ "typefest/prefer-ts-extras-is-property-defined": "error",
75
+ },
76
+ },
77
+ ];
78
+ ```
79
+
80
+ ## When not to use it
81
+
82
+ Disable this rule if your filter callbacks intentionally combine property checks with additional logic, or if the property name is dynamic.
83
+
84
+ ## Package documentation
85
+
86
+ ts-extras package documentation:
87
+
88
+ Source file: [`source/is-property-defined.ts`](https://github.com/sindresorhus/ts-extras/blob/main/source/is-property-defined.ts)
89
+
90
+ ````ts
91
+ /**
92
+ Returns a filter predicate that tests whether a given property key is defined (not `undefined`) on an object.
93
+
94
+ This is useful as a type guard in `Array.prototype.filter` to narrow the resulting array type.
95
+
96
+ @example
97
+ ```
98
+ import {isPropertyDefined} from 'ts-extras';
99
+
100
+ interface User {
101
+ name: string | undefined;
102
+ }
103
+
104
+ const users: User[] = [{ name: 'Alice' }, { name: undefined }];
105
+ const namedUsers = users.filter(isPropertyDefined('name'));
106
+ //=> [{ name: 'Alice' }]
107
+ ```
108
+
109
+ @category Type guard
110
+ */
111
+ ````
112
+
113
+ > **Rule catalog ID:** R101
114
+
115
+ ## Further reading
116
+
117
+ - [`ts-extras` README](https://github.com/sindresorhus/ts-extras)
118
+ - [`ts-extras` package reference](https://www.npmjs.com/package/ts-extras)
119
+ - [TypeScript Handbook: Narrowing](https://www.typescriptlang.org/docs/handbook/2/narrowing.html)
@@ -0,0 +1,118 @@
1
+ # prefer-ts-extras-is-property-present
2
+
3
+ Require [`isPropertyPresent`](https://github.com/sindresorhus/ts-extras/blob/main/source/is-property-present.ts) from `ts-extras` in `Array.prototype.filter` callbacks instead of inline property-nullish checks.
4
+
5
+ ## Targeted pattern scope
6
+
7
+ This rule only inspects inline `.filter(...)` predicates that perform an explicit loose-null check against a single object property.
8
+
9
+ - Inline property-nullish predicates inside `.filter(...)`, including:
10
+ - `filter((item) => item.prop != null)`
11
+ - `filter((item) => null != item.prop)`
12
+
13
+ Named predicate references, multi-argument callbacks, and stricter equality checks are not matched.
14
+
15
+ ## What this rule reports
16
+
17
+ This rule reports inline filter predicates that check whether a single object property is not `null` (using loose equality, which also catches `undefined`) and can be normalized with `isPropertyPresent`.
18
+
19
+ ## Why this rule exists
20
+
21
+ `filter(isPropertyPresent('prop'))` is the canonical `ts-extras` pattern for filtering out items where a specific property is `null` or `undefined`.
22
+
23
+ - Filtering logic is consistent and composable across collections.
24
+ - The property key is explicit in the function call, not embedded inside a callback expression.
25
+ - Repeated inline `!= null` callback expressions are removed.
26
+ - `isPropertyPresent` is a proper type predicate that narrows element types in the resulting array to exclude both `null` and `undefined`.
27
+
28
+ ## ❌ Incorrect
29
+
30
+ ```ts
31
+ const titled = posts.filter((post) => post.title != null);
32
+ ```
33
+
34
+ ## ✅ Correct
35
+
36
+ ```ts
37
+ import { isPropertyPresent } from "ts-extras";
38
+
39
+ const titled = posts.filter(isPropertyPresent("title"));
40
+ ```
41
+
42
+ ## Behavior and migration notes
43
+
44
+ - `isPropertyPresent('prop')` checks `item[prop] != null`, which is `true` when the value is neither `null` nor `undefined`.
45
+ - The autofix preserves the property name as a string literal.
46
+ - Strict null checks (e.g., `post.title !== null`) are intentionally excluded — those do not narrow away `undefined`.
47
+ - Deep property access (e.g., `post.meta.title != null`) is intentionally excluded — only single-level property checks are flagged.
48
+ - Computed property access (e.g., `post[key] != null`) is intentionally excluded.
49
+
50
+ ## Additional examples
51
+
52
+ ### ❌ Incorrect — reversed operands
53
+
54
+ ```ts
55
+ const titled = posts.filter((post) => null != post.title);
56
+ ```
57
+
58
+ ### ✅ Correct — reversed operands fixed
59
+
60
+ ```ts
61
+ const titled = posts.filter(isPropertyPresent("title"));
62
+ ```
63
+
64
+ ## ESLint flat config example
65
+
66
+ ```ts
67
+ import typefest from "eslint-plugin-typefest";
68
+
69
+ export default [
70
+ {
71
+ plugins: { typefest },
72
+ rules: {
73
+ "typefest/prefer-ts-extras-is-property-present": "error",
74
+ },
75
+ },
76
+ ];
77
+ ```
78
+
79
+ ## When not to use it
80
+
81
+ Disable this rule if your filter callbacks intentionally combine property checks with additional logic, or if the property name is dynamic.
82
+
83
+ ## Package documentation
84
+
85
+ ts-extras package documentation:
86
+
87
+ Source file: [`source/is-property-present.ts`](https://github.com/sindresorhus/ts-extras/blob/main/source/is-property-present.ts)
88
+
89
+ ````ts
90
+ /**
91
+ Returns a filter predicate that tests whether a given property key is present (non-nullable) on an object.
92
+
93
+ This is useful as a type guard in `Array.prototype.filter` to narrow the resulting array type by removing `null` and `undefined` property values.
94
+
95
+ @example
96
+ ```
97
+ import {isPropertyPresent} from 'ts-extras';
98
+
99
+ interface Post {
100
+ title: string | null | undefined;
101
+ }
102
+
103
+ const posts: Post[] = [{ title: 'Hello' }, { title: null }];
104
+ const titledPosts = posts.filter(isPropertyPresent('title'));
105
+ //=> [{ title: 'Hello' }]
106
+ ```
107
+
108
+ @category Type guard
109
+ */
110
+ ````
111
+
112
+ > **Rule catalog ID:** R102
113
+
114
+ ## Further reading
115
+
116
+ - [`ts-extras` README](https://github.com/sindresorhus/ts-extras)
117
+ - [`ts-extras` package reference](https://www.npmjs.com/package/ts-extras)
118
+ - [TypeScript Handbook: Narrowing](https://www.typescriptlang.org/docs/handbook/2/narrowing.html)
@@ -0,0 +1,99 @@
1
+ # prefer-type-fest-absolute
2
+
3
+ Require TypeFest [`Absolute`](https://github.com/sindresorhus/type-fest/blob/main/source/absolute.d.ts) over common `Abs` or `AbsoluteValue` aliases.
4
+
5
+ ## Targeted pattern scope
6
+
7
+ This rule reports `Abs<N>` and `AbsoluteValue<N>` type references and prefers the canonical `Absolute<N>` from type-fest for numeric absolute-value type computations.
8
+
9
+ ## What this rule reports
10
+
11
+ - Type references named `Abs`.
12
+ - Type references named `AbsoluteValue`.
13
+
14
+ ### Detection boundaries
15
+
16
+ - ✅ Reports direct `Abs<N>` and `AbsoluteValue<N>` type references.
17
+ - ✅ Autofixes by renaming the identifier to `Absolute` and inserting a `type-fest` import when absent.
18
+ - ❌ Does not auto-fix where the `Absolute` identifier is shadowed by a type parameter in scope.
19
+
20
+ ## Why this rule exists
21
+
22
+ `Absolute<N>` is the canonical TypeFest utility for computing the absolute value of a numeric literal type.
23
+
24
+ Using a consistent name across a codebase avoids confusion between locally-defined `Abs` helpers and the standard TypeFest utility. A single canonical name also makes the intent immediately readable by contributors familiar with type-fest.
25
+
26
+ ## ❌ Incorrect
27
+
28
+ ```ts
29
+ type Result = Abs<-5>;
30
+ type Other = AbsoluteValue<-100>;
31
+ ```
32
+
33
+ ## ✅ Correct
34
+
35
+ ```ts
36
+ import type { Absolute } from "type-fest";
37
+
38
+ type Result = Absolute<-5>;
39
+ type Other = Absolute<-100>;
40
+ ```
41
+
42
+ ## Behavior and migration notes
43
+
44
+ - `Absolute<N>` strips the leading minus sign from a negative numeric literal type, producing the non-negative form.
45
+ - Locally-defined `Abs` or `AbsoluteValue` helpers may have different semantics (e.g., different constraints). Verify the behavior is equivalent before applying the autofix.
46
+ - The autofix is safe to apply when the local alias is a mere re-export or thin wrapper over `Absolute`.
47
+
48
+ ## ESLint flat config example
49
+
50
+ ```ts
51
+ import typefest from "eslint-plugin-typefest";
52
+
53
+ export default [
54
+ {
55
+ plugins: { typefest },
56
+ rules: {
57
+ "typefest/prefer-type-fest-absolute": "error",
58
+ },
59
+ },
60
+ ];
61
+ ```
62
+
63
+ ## When not to use it
64
+
65
+ Disable this rule if your codebase intentionally standardizes `Abs` or `AbsoluteValue` naming, or if your local alias provides additional constraints not present in the TypeFest utility.
66
+
67
+ ## Package documentation
68
+
69
+ TypeFest package documentation:
70
+
71
+ Source file: [`source/absolute.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/absolute.d.ts)
72
+
73
+ ````ts
74
+ /**
75
+ Returns the absolute value of a given integer type.
76
+
77
+ @example
78
+ ```
79
+ import type {Absolute} from 'type-fest';
80
+
81
+ type SomeValue = Absolute<-1>;
82
+ //=> 1
83
+ ```
84
+
85
+ @category Numeric
86
+ */
87
+ ````
88
+
89
+ > **Rule catalog ID:** R097
90
+
91
+ ## Further reading
92
+
93
+ - [TypeFest README](https://github.com/sindresorhus/type-fest)
94
+ - [TypeScript Handbook: Utility Types](https://www.typescriptlang.org/docs/handbook/utility-types.html)
95
+
96
+ ## Adoption resources
97
+
98
+ - [Rule adoption checklist](./guides/adoption-checklist.md)
99
+ - [Rollout and fix safety](./guides/rollout-and-fix-safety.md)
@@ -0,0 +1,105 @@
1
+ # prefer-type-fest-non-nullable-deep
2
+
3
+ Require TypeFest [`NonNullableDeep`](https://github.com/sindresorhus/type-fest/blob/main/source/non-nullable-deep.d.ts) over `DeepNonNullable` aliases.
4
+
5
+ ## Targeted pattern scope
6
+
7
+ This rule reports `DeepNonNullable<T>` type references and prefers the canonical `NonNullableDeep<T>` from type-fest for recursive non-nullable transformations.
8
+
9
+ ## What this rule reports
10
+
11
+ - Type references named `DeepNonNullable`.
12
+
13
+ ### Detection boundaries
14
+
15
+ - ✅ Reports direct `DeepNonNullable<T>` type references.
16
+ - ✅ Autofixes by renaming the identifier to `NonNullableDeep` and inserting a `type-fest` import when absent.
17
+ - ❌ Does not auto-fix where the `NonNullableDeep` identifier is shadowed by a type parameter in scope.
18
+
19
+ ## Why this rule exists
20
+
21
+ `NonNullableDeep<T>` is the canonical TypeFest utility for recursively removing `null` and `undefined` from all nested properties.
22
+
23
+ Using a consistent name avoids confusion between locally-defined deep-non-nullable helpers and the official TypeFest utility. The canonical name also communicates intent to contributors familiar with type-fest.
24
+
25
+ ## ❌ Incorrect
26
+
27
+ ```ts
28
+ type StrictConfig = DeepNonNullable<Config>;
29
+ ```
30
+
31
+ ## ✅ Correct
32
+
33
+ ```ts
34
+ import type { NonNullableDeep } from "type-fest";
35
+
36
+ type StrictConfig = NonNullableDeep<Config>;
37
+ ```
38
+
39
+ ## Behavior and migration notes
40
+
41
+ - `NonNullableDeep<T>` recursively removes `null` and `undefined` from all nested object properties.
42
+ - Validate parity if your legacy `DeepNonNullable` alias had different behavior for arrays, maps, or sets.
43
+ - Prefer explicit narrowing over deep non-nullable transformation where the required shape is known at the call site.
44
+
45
+ ## ESLint flat config example
46
+
47
+ ```ts
48
+ import typefest from "eslint-plugin-typefest";
49
+
50
+ export default [
51
+ {
52
+ plugins: { typefest },
53
+ rules: {
54
+ "typefest/prefer-type-fest-non-nullable-deep": "error",
55
+ },
56
+ },
57
+ ];
58
+ ```
59
+
60
+ ## When not to use it
61
+
62
+ Disable this rule if your codebase intentionally standardizes `DeepNonNullable` naming or if your local alias provides additional constraints not present in the TypeFest utility.
63
+
64
+ ## Package documentation
65
+
66
+ TypeFest package documentation:
67
+
68
+ Source file: [`source/non-nullable-deep.d.ts`](https://github.com/sindresorhus/type-fest/blob/main/source/non-nullable-deep.d.ts)
69
+
70
+ ````ts
71
+ /**
72
+ Deeply remove `null` and `undefined` from all properties of `T`.
73
+
74
+ Use-cases:
75
+ - Removing optional and nullable markers after a data-hydration step.
76
+ - Ensuring a configuration object has all required values present.
77
+
78
+ @example
79
+ ```
80
+ import type {NonNullableDeep} from 'type-fest';
81
+
82
+ interface Config {
83
+ host: string | null;
84
+ port: number | undefined;
85
+ }
86
+
87
+ type StrictConfig = NonNullableDeep<Config>;
88
+ // => { host: string; port: number }
89
+ ```
90
+
91
+ @category Object
92
+ */
93
+ ````
94
+
95
+ > **Rule catalog ID:** R098
96
+
97
+ ## Further reading
98
+
99
+ - [TypeFest README](https://github.com/sindresorhus/type-fest)
100
+ - [TypeScript Handbook: Utility Types](https://www.typescriptlang.org/docs/handbook/utility-types.html)
101
+
102
+ ## Adoption resources
103
+
104
+ - [Rule adoption checklist](./guides/adoption-checklist.md)
105
+ - [Rollout and fix safety](./guides/rollout-and-fix-safety.md)