eslint-plugin-typefest 1.0.3 → 1.0.5

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 (61) hide show
  1. package/README.md +18 -2
  2. package/dist/_internal/rule-catalog.d.ts.map +1 -1
  3. package/dist/_internal/rule-catalog.js +9 -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 +18 -0
  7. package/dist/_internal/rules-registry.js.map +1 -1
  8. package/dist/plugin.cjs +866 -36
  9. package/dist/plugin.cjs.map +4 -4
  10. package/dist/rules/prefer-type-fest-and-all.d.ts +13 -0
  11. package/dist/rules/prefer-type-fest-and-all.d.ts.map +1 -0
  12. package/dist/rules/prefer-type-fest-and-all.js +105 -0
  13. package/dist/rules/prefer-type-fest-and-all.js.map +1 -0
  14. package/dist/rules/prefer-type-fest-array-length.d.ts +13 -0
  15. package/dist/rules/prefer-type-fest-array-length.d.ts.map +1 -0
  16. package/dist/rules/prefer-type-fest-array-length.js +77 -0
  17. package/dist/rules/prefer-type-fest-array-length.js.map +1 -0
  18. package/dist/rules/prefer-type-fest-conditional-pick-deep.d.ts +13 -0
  19. package/dist/rules/prefer-type-fest-conditional-pick-deep.d.ts.map +1 -0
  20. package/dist/rules/prefer-type-fest-conditional-pick-deep.js +75 -0
  21. package/dist/rules/prefer-type-fest-conditional-pick-deep.js.map +1 -0
  22. package/dist/rules/prefer-type-fest-less-than-or-equal.d.ts +13 -0
  23. package/dist/rules/prefer-type-fest-less-than-or-equal.d.ts.map +1 -0
  24. package/dist/rules/prefer-type-fest-less-than-or-equal.js +153 -0
  25. package/dist/rules/prefer-type-fest-less-than-or-equal.js.map +1 -0
  26. package/dist/rules/prefer-type-fest-less-than.d.ts +13 -0
  27. package/dist/rules/prefer-type-fest-less-than.d.ts.map +1 -0
  28. package/dist/rules/prefer-type-fest-less-than.js +154 -0
  29. package/dist/rules/prefer-type-fest-less-than.js.map +1 -0
  30. package/dist/rules/prefer-type-fest-optional.d.ts +13 -0
  31. package/dist/rules/prefer-type-fest-optional.d.ts.map +1 -0
  32. package/dist/rules/prefer-type-fest-optional.js +130 -0
  33. package/dist/rules/prefer-type-fest-optional.js.map +1 -0
  34. package/dist/rules/prefer-type-fest-or-all.d.ts +13 -0
  35. package/dist/rules/prefer-type-fest-or-all.d.ts.map +1 -0
  36. package/dist/rules/prefer-type-fest-or-all.js +105 -0
  37. package/dist/rules/prefer-type-fest-or-all.js.map +1 -0
  38. package/dist/rules/prefer-type-fest-union-member.d.ts +13 -0
  39. package/dist/rules/prefer-type-fest-union-member.d.ts.map +1 -0
  40. package/dist/rules/prefer-type-fest-union-member.js +159 -0
  41. package/dist/rules/prefer-type-fest-union-member.js.map +1 -0
  42. package/dist/rules/prefer-type-fest-union-to-tuple.d.ts +13 -0
  43. package/dist/rules/prefer-type-fest-union-to-tuple.d.ts.map +1 -0
  44. package/dist/rules/prefer-type-fest-union-to-tuple.js +75 -0
  45. package/dist/rules/prefer-type-fest-union-to-tuple.js.map +1 -0
  46. package/docs/rules/prefer-type-fest-and-all.md +111 -0
  47. package/docs/rules/prefer-type-fest-array-length.md +109 -0
  48. package/docs/rules/prefer-type-fest-conditional-pick-deep.md +112 -0
  49. package/docs/rules/prefer-type-fest-less-than-or-equal.md +111 -0
  50. package/docs/rules/prefer-type-fest-less-than.md +111 -0
  51. package/docs/rules/prefer-type-fest-optional.md +104 -0
  52. package/docs/rules/prefer-type-fest-or-all.md +111 -0
  53. package/docs/rules/prefer-type-fest-union-member.md +119 -0
  54. package/docs/rules/prefer-type-fest-union-to-tuple.md +108 -0
  55. package/docs/rules/presets/all.md +9 -0
  56. package/docs/rules/presets/index.md +87 -78
  57. package/docs/rules/presets/recommended-type-checked.md +74 -65
  58. package/docs/rules/presets/recommended.md +8 -0
  59. package/docs/rules/presets/strict.md +9 -0
  60. package/docs/rules/presets/type-fest-types.md +8 -0
  61. package/package.json +32 -25
package/dist/plugin.cjs CHANGED
@@ -34,13 +34,13 @@ __export(plugin_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(plugin_exports);
36
36
  var import_parser3 = __toESM(require("@typescript-eslint/parser"), 1);
37
- var import_ts_extras37 = require("ts-extras");
37
+ var import_ts_extras39 = require("ts-extras");
38
38
 
39
39
  // package.json
40
40
  var package_default = {
41
41
  $schema: "https://www.schemastore.org/package.json",
42
42
  name: "eslint-plugin-typefest",
43
- version: "1.0.3",
43
+ version: "1.0.5",
44
44
  private: false,
45
45
  description: "ESLint rules for adopting type-fest and ts-extras conventions.",
46
46
  keywords: [
@@ -61,12 +61,12 @@ var package_default = {
61
61
  url: "git+https://github.com/Nick2bad4u/eslint-plugin-typefest.git"
62
62
  },
63
63
  license: "MIT",
64
- author: "Nick2bad4u <20943337+Nick2bad4u@users.noreply.github.com> (https://nick2bad4u.github.io/eslint-plugin-typefest)",
64
+ author: "Nick2bad4u <20943337+Nick2bad4u@users.noreply.github.com> (https://github.com/Nick2bad4u)",
65
65
  contributors: [
66
66
  {
67
67
  name: "Nick2bad4u",
68
68
  email: "20943337+Nick2bad4u@users.noreply.github.com",
69
- url: "https://nick2bad4u.github.io/eslint-plugin-typefest"
69
+ url: "https://github.com/Nick2bad4u"
70
70
  }
71
71
  ],
72
72
  sideEffects: false,
@@ -115,6 +115,8 @@ var package_default = {
115
115
  "build:clean": `node -e "require('node:fs').rmSync('dist',{recursive:true,force:true})"`,
116
116
  "build:eslint-inspector": 'npx -y @eslint/config-inspector@1.4.2 build --outDir "docs/docusaurus/static/eslint-inspector" --base "/eslint-plugin-typefest/eslint-inspector/"',
117
117
  "build:eslint-inspector:local": "npx @eslint/config-inspector",
118
+ "build:stylelint-inspector": 'npx -y stylelint-config-inspector@latest build --outDir "docs/docusaurus/static/stylelint-inspector" --base "/eslint-plugin-typefest/stylelint-inspector/"',
119
+ "build:stylelint-inspector:local": "npx stylelint-config-inspector@latest",
118
120
  "build:types:cjs": `node -e "require('node:fs').copyFileSync('dist/plugin.d.ts','dist/plugin.d.cts')"`,
119
121
  "changelog:generate": "git-cliff --config cliff.toml --output CHANGELOG.md",
120
122
  "changelog:preview": "git-cliff --config cliff.toml --unreleased",
@@ -146,8 +148,10 @@ var package_default = {
146
148
  "docs:build": "npm run --workspace docs/docusaurus build",
147
149
  "docs:build:local": "npm run --workspace docs/docusaurus build:local",
148
150
  "docs:check-links": "npm run docs:api && node ./scripts/check-doc-links.mjs",
151
+ "docs:devtools:metadata": "node scripts/generate-devtools-workspace-metadata.mjs",
149
152
  "docs:serve": "npm run --workspace docs/docusaurus serve",
150
153
  "docs:start": "npm run --workspace docs/docusaurus start",
154
+ "docs:start:devtools": "npm run docs:devtools:metadata && npm run docs:api:local && npm run --workspace docs/docusaurus start:devtools",
151
155
  "docs:toc": "remark docs --use remark-toc --output",
152
156
  "docs:typecheck": "npm run --workspace docs/docusaurus typecheck",
153
157
  "docs:typedoc": "npm run --workspace docs/docusaurus docs:api",
@@ -209,7 +213,7 @@ var package_default = {
209
213
  "open:coverage": "open-cli coverage/index.html",
210
214
  prepublishOnly: "npm run release:check",
211
215
  "release:check": "npm run release:verify",
212
- "release:verify": "npm run build && npm run lint && npm run typecheck && npm run test && npm run sync:readme-rules-table && npm run sync:presets-rules-matrix && npm run docs:check-links && npm pack --dry-run",
216
+ "release:verify": "cross-env NODE_OPTIONS= npm run build && cross-env NODE_OPTIONS= npm run lint && cross-env NODE_OPTIONS= npm run typecheck && cross-env NODE_OPTIONS= VITEST_TYPECHECK=false npm run test && cross-env NODE_OPTIONS= npm run sync:readme-rules-table && cross-env NODE_OPTIONS= npm run sync:presets-rules-matrix && cross-env NODE_OPTIONS= npm run docs:check-links && cross-env NODE_OPTIONS= npm pack --dry-run",
213
217
  "remark:fix": 'remark --rc-path .remarkrc.mjs --silently-ignore --ignore-path .remarkignore --frail --quiet --output -- "*.{md,mdx}" "docs/**/*.{md,mdx}"',
214
218
  "remark:test-config": 'remark --rc-path .remarkrc.mjs --silently-ignore --ignore-path .remarkignore --frail "README.md"',
215
219
  "sync:node-version-files": "node scripts/sync-node-version-files.mjs",
@@ -250,20 +254,20 @@ var package_default = {
250
254
  "jsonc-eslint-parser": "$jsonc-eslint-parser"
251
255
  },
252
256
  dependencies: {
253
- "@typescript-eslint/parser": "^8.57.0",
254
- "@typescript-eslint/type-utils": "^8.57.0",
255
- "@typescript-eslint/utils": "^8.57.0",
257
+ "@typescript-eslint/parser": "^8.57.1",
258
+ "@typescript-eslint/type-utils": "^8.57.1",
259
+ "@typescript-eslint/utils": "^8.57.1",
256
260
  "ts-extras": "^0.17.0",
257
- "type-fest": "^5.4.4"
261
+ "type-fest": "^5.5.0"
258
262
  },
259
263
  devDependencies: {
260
264
  "@arethetypeswrong/cli": "^0.18.2",
261
265
  "@csstools/stylelint-formatter-github": "^2.0.0",
262
266
  "@docusaurus/eslint-plugin": "^3.9.2",
263
267
  "@double-great/remark-lint-alt-text": "^1.1.1",
264
- "@double-great/stylelint-a11y": "^3.4.5",
268
+ "@double-great/stylelint-a11y": "^3.4.6",
265
269
  "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1",
266
- "@eslint-react/eslint-plugin": "^2.13.0",
270
+ "@eslint-react/eslint-plugin": "^3.0.0",
267
271
  "@eslint/compat": "^2.0.3",
268
272
  "@eslint/config-helpers": "^0.5.3",
269
273
  "@eslint/config-inspector": "^1.5.0",
@@ -311,8 +315,8 @@ var package_default = {
311
315
  "@types/postcss-normalize": "^9.0.4",
312
316
  "@types/postcss-reporter": "^7.0.5",
313
317
  "@types/sloc": "^0.2.3",
314
- "@typescript-eslint/eslint-plugin": "^8.57.0",
315
- "@typescript-eslint/rule-tester": "^8.57.0",
318
+ "@typescript-eslint/eslint-plugin": "^8.57.1",
319
+ "@typescript-eslint/rule-tester": "^8.57.1",
316
320
  "@vitest/coverage-v8": "^4.1.0",
317
321
  "@vitest/eslint-plugin": "^1.6.12",
318
322
  "@vitest/ui": "^4.1.0",
@@ -338,6 +342,7 @@ var package_default = {
338
342
  "eslint-plugin-depend": "^1.5.0",
339
343
  "eslint-plugin-eslint-plugin": "^7.3.2",
340
344
  "eslint-plugin-etc": "^2.0.3",
345
+ "eslint-plugin-etc-misc": "^1.0.3",
341
346
  "eslint-plugin-file-progress-2": "^3.4.3",
342
347
  "eslint-plugin-html": "^8.1.4",
343
348
  "eslint-plugin-import-x": "^4.16.2",
@@ -360,7 +365,7 @@ var package_default = {
360
365
  "eslint-plugin-no-use-extend-native": "^0.7.2",
361
366
  "eslint-plugin-node-dependencies": "^2.2.0",
362
367
  "eslint-plugin-package-json": "^0.91.0",
363
- "eslint-plugin-perfectionist": "^5.6.0",
368
+ "eslint-plugin-perfectionist": "^5.7.0",
364
369
  "eslint-plugin-prefer-arrow": "^1.2.3",
365
370
  "eslint-plugin-prettier": "^5.5.5",
366
371
  "eslint-plugin-promise": "^7.2.1",
@@ -370,11 +375,12 @@ var package_default = {
370
375
  "eslint-plugin-security": "^4.0.0",
371
376
  "eslint-plugin-sonarjs": "^4.0.2",
372
377
  "eslint-plugin-sort-class-members": "^1.21.0",
373
- "eslint-plugin-testing-library": "^7.16.0",
378
+ "eslint-plugin-testing-library": "^7.16.1",
374
379
  "eslint-plugin-toml": "^1.3.1",
375
380
  "eslint-plugin-total-functions": "^7.1.0",
376
381
  "eslint-plugin-tsdoc": "^0.5.2",
377
- "eslint-plugin-tsdoc-require-2": "^1.0.4",
382
+ "eslint-plugin-tsdoc-require-2": "^1.0.5",
383
+ "eslint-plugin-typefest": "^1.0.4",
378
384
  "eslint-plugin-undefined-css-classes": "^0.1.5",
379
385
  "eslint-plugin-unicorn": "^63.0.0",
380
386
  "eslint-plugin-unused-imports": "^4.4.1",
@@ -388,11 +394,11 @@ var package_default = {
388
394
  htmlhint: "^1.9.2",
389
395
  jscpd: "^4.0.8",
390
396
  "jsonc-eslint-parser": "^3.1.0",
391
- knip: "^5.86.0",
397
+ knip: "^5.88.1",
392
398
  leasot: "^14.4.0",
393
399
  madge: "^8.0.0",
394
400
  "markdown-link-check": "^3.14.2",
395
- "npm-check-updates": "^19.6.3",
401
+ "npm-check-updates": "^19.6.5",
396
402
  "npm-package-json-lint": "^9.1.0",
397
403
  picocolors: "^1.1.1",
398
404
  postcss: "^8.5.8",
@@ -535,13 +541,14 @@ var package_default = {
535
541
  secretlint: "^11.3.1",
536
542
  sloc: "^0.3.2",
537
543
  "sort-package-json": "^3.6.1",
538
- stylelint: "^17.4.0",
544
+ stylelint: "^17.5.0",
539
545
  "stylelint-actions-formatters": "^16.3.1",
540
546
  "stylelint-checkstyle-formatter": "^0.1.2",
541
547
  "stylelint-codeframe-formatter": "^1.2.0",
542
548
  "stylelint-config-alphabetical-order": "^2.0.0",
543
549
  "stylelint-config-idiomatic-order": "^10.0.0",
544
- "stylelint-config-recess-order": "^7.6.1",
550
+ "stylelint-config-inspector": "^2.0.1",
551
+ "stylelint-config-recess-order": "^7.7.0",
545
552
  "stylelint-config-recommended": "^18.0.0",
546
553
  "stylelint-config-sass-guidelines": "^13.0.0",
547
554
  "stylelint-config-standard": "^40.0.0",
@@ -563,7 +570,7 @@ var package_default = {
563
570
  "stylelint-no-unresolved-module": "^2.5.2",
564
571
  "stylelint-no-unsupported-browser-features": "^8.1.1",
565
572
  "stylelint-order": "^8.1.1",
566
- "stylelint-plugin-defensive-css": "^2.6.0",
573
+ "stylelint-plugin-defensive-css": "^2.8.0",
567
574
  "stylelint-plugin-logical-css": "^2.0.2",
568
575
  "stylelint-plugin-use-baseline": "^1.2.7",
569
576
  "stylelint-prettier": "^5.0.3",
@@ -576,10 +583,10 @@ var package_default = {
576
583
  "ts-unused-exports": "^11.0.1",
577
584
  typedoc: "^0.28.17",
578
585
  typescript: "^5.9.3",
579
- "typescript-eslint": "^8.57.0",
586
+ "typescript-eslint": "^8.57.1",
580
587
  typesync: "^0.14.3",
581
588
  vfile: "^6.0.3",
582
- vite: "^8.0.0",
589
+ vite: "^8.0.1",
583
590
  "vite-tsconfig-paths": "^6.1.1",
584
591
  vitest: "^4.1.0",
585
592
  "yaml-eslint-parser": "^2.0.0",
@@ -589,14 +596,14 @@ var package_default = {
589
596
  eslint: "^9.0.0 || ^10.0.3",
590
597
  typescript: ">=5.0.0"
591
598
  },
592
- packageManager: "npm@11.11.1",
599
+ packageManager: "npm@11.12.0",
593
600
  engines: {
594
- node: ">=20.19.0"
601
+ node: ">=22.0.0"
595
602
  },
596
603
  devEngines: {
597
604
  runtime: {
598
605
  name: "node",
599
- version: ">=20.19.0",
606
+ version: ">=22.0.0",
600
607
  onFail: "error"
601
608
  },
602
609
  packageManager: {
@@ -1165,6 +1172,13 @@ var evaluateIsArrayLikeType = ({ candidateType, checker, resolutionCache, seenTy
1165
1172
  resolutionCache.set(candidateType, false);
1166
1173
  return false;
1167
1174
  };
1175
+ var isArrayLikeType = (checker, type, unionMatchMode = "some") => evaluateIsArrayLikeType({
1176
+ candidateType: type,
1177
+ checker,
1178
+ resolutionCache: /* @__PURE__ */ new Map(),
1179
+ seenTypes: /* @__PURE__ */ new Set(),
1180
+ unionMatchMode
1181
+ });
1168
1182
  var getArrayLikeExpressionPrefilterResult = (expression) => {
1169
1183
  if (expression.type === "ArrayExpression") {
1170
1184
  return true;
@@ -2322,7 +2336,16 @@ var orderedRuleNames = [
2322
2336
  "prefer-type-fest-unwrap-tagged",
2323
2337
  "prefer-type-fest-value-of",
2324
2338
  "prefer-type-fest-writable",
2325
- "prefer-type-fest-writable-deep"
2339
+ "prefer-type-fest-writable-deep",
2340
+ "prefer-type-fest-and-all",
2341
+ "prefer-type-fest-array-length",
2342
+ "prefer-type-fest-optional",
2343
+ "prefer-type-fest-or-all",
2344
+ "prefer-type-fest-union-member",
2345
+ "prefer-type-fest-conditional-pick-deep",
2346
+ "prefer-type-fest-union-to-tuple",
2347
+ "prefer-type-fest-less-than",
2348
+ "prefer-type-fest-less-than-or-equal"
2326
2349
  ];
2327
2350
  var toRuleCatalogId = (ruleNumber) => `R${String(ruleNumber).padStart(3, "0")}`;
2328
2351
  var isTypefestRuleNamePattern2 = (ruleName) => ruleName.startsWith("prefer-");
@@ -6607,6 +6630,140 @@ var preferTypeFestAbstractConstructorRule = createTypedRule({
6607
6630
  });
6608
6631
  var prefer_type_fest_abstract_constructor_default = preferTypeFestAbstractConstructorRule;
6609
6632
 
6633
+ // dist/rules/prefer-type-fest-and-all.js
6634
+ var ALL_EXTEND_TYPE_NAME = "AllExtend";
6635
+ var AND_ALL_TYPE_NAME = "AndAll";
6636
+ var isTrueLiteralType = (node) => node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === true;
6637
+ var preferTypeFestAndAllRule = createTypedRule({
6638
+ create(context) {
6639
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
6640
+ const allExtendLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, ALL_EXTEND_TYPE_NAME);
6641
+ const typeFestNamespaceImportNames = collectNamespaceImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
6642
+ const getAllExtendTupleArgumentText = (typeReference) => {
6643
+ const typeArguments = typeReference.typeArguments?.params ?? [];
6644
+ const [tupleArgument, comparedType] = typeArguments;
6645
+ if (!tupleArgument || !comparedType || !isTrueLiteralType(comparedType)) {
6646
+ return null;
6647
+ }
6648
+ if (typeArguments.length !== 2) {
6649
+ return null;
6650
+ }
6651
+ return context.sourceCode.getText(tupleArgument);
6652
+ };
6653
+ const reportIfAllExtendEquivalent = (node) => {
6654
+ const tupleArgumentText = getAllExtendTupleArgumentText(node);
6655
+ if (tupleArgumentText === null || tupleArgumentText.trim().length === 0) {
6656
+ return;
6657
+ }
6658
+ const fix = createSafeTypeNodeTextReplacementFix(node, AND_ALL_TYPE_NAME, `${AND_ALL_TYPE_NAME}<${tupleArgumentText}>`, typeFestDirectImports);
6659
+ reportWithOptionalFix({
6660
+ context,
6661
+ fix,
6662
+ messageId: "preferAndAll",
6663
+ node
6664
+ });
6665
+ };
6666
+ return {
6667
+ 'TSTypeReference[typeName.type="Identifier"]'(typeReference) {
6668
+ if (typeReference.typeName.type !== "Identifier" || !setContainsValue(allExtendLocalNames, typeReference.typeName.name)) {
6669
+ return;
6670
+ }
6671
+ reportIfAllExtendEquivalent(typeReference);
6672
+ },
6673
+ 'TSTypeReference[typeName.type="TSQualifiedName"]'(typeReference) {
6674
+ if (typeReference.typeName.type !== "TSQualifiedName") {
6675
+ return;
6676
+ }
6677
+ if (typeReference.typeName.left.type !== "Identifier" || !setContainsValue(typeFestNamespaceImportNames, typeReference.typeName.left.name) || typeReference.typeName.right.type !== "Identifier" || typeReference.typeName.right.name !== ALL_EXTEND_TYPE_NAME) {
6678
+ return;
6679
+ }
6680
+ reportIfAllExtendEquivalent(typeReference);
6681
+ }
6682
+ };
6683
+ },
6684
+ defaultOptions: [],
6685
+ meta: {
6686
+ deprecated: false,
6687
+ docs: {
6688
+ description: "require TypeFest AndAll over `AllExtend<TTuple, true>` boolean-tuple checks.",
6689
+ frozen: false,
6690
+ recommended: true,
6691
+ requiresTypeChecking: false,
6692
+ typefestConfigs: [
6693
+ "typefest.configs.recommended",
6694
+ "typefest.configs.strict",
6695
+ "typefest.configs.all",
6696
+ "typefest.configs.type-fest/types"
6697
+ ],
6698
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-and-all"
6699
+ },
6700
+ fixable: "code",
6701
+ messages: {
6702
+ preferAndAll: "Prefer `AndAll<TTuple>` from type-fest over `AllExtend<TTuple, true>` for boolean-tuple conjunction checks."
6703
+ },
6704
+ schema: [],
6705
+ type: "suggestion"
6706
+ },
6707
+ name: "prefer-type-fest-and-all"
6708
+ });
6709
+ var prefer_type_fest_and_all_default = preferTypeFestAndAllRule;
6710
+
6711
+ // dist/rules/prefer-type-fest-array-length.js
6712
+ var ARRAY_LENGTH_TYPE_NAME = "ArrayLength";
6713
+ var isLengthIndexType = (node) => node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === "length";
6714
+ var preferTypeFestArrayLengthRule = createTypedRule({
6715
+ create(context) {
6716
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
6717
+ const { checker, parserServices } = getTypedRuleServices(context);
6718
+ return {
6719
+ TSIndexedAccessType(node) {
6720
+ if (!isLengthIndexType(node.indexType)) {
6721
+ return;
6722
+ }
6723
+ const objectType = getConstrainedTypeAtLocationWithFallback(checker, node.objectType, parserServices, "prefer-type-fest-array-length-type-resolution-failed");
6724
+ if (!objectType || !isArrayLikeType(checker, objectType, "every")) {
6725
+ return;
6726
+ }
6727
+ const objectTypeText = context.sourceCode.getText(node.objectType);
6728
+ if (objectTypeText.trim().length === 0) {
6729
+ return;
6730
+ }
6731
+ const fix = createSafeTypeNodeTextReplacementFix(node, ARRAY_LENGTH_TYPE_NAME, `${ARRAY_LENGTH_TYPE_NAME}<${objectTypeText}>`, typeFestDirectImports);
6732
+ reportWithOptionalFix({
6733
+ context,
6734
+ fix,
6735
+ messageId: "preferArrayLength",
6736
+ node
6737
+ });
6738
+ }
6739
+ };
6740
+ },
6741
+ defaultOptions: [],
6742
+ meta: {
6743
+ deprecated: false,
6744
+ docs: {
6745
+ description: 'require TypeFest ArrayLength over array and tuple `T["length"]` type queries.',
6746
+ frozen: false,
6747
+ recommended: false,
6748
+ requiresTypeChecking: true,
6749
+ typefestConfigs: [
6750
+ "typefest.configs.recommended-type-checked",
6751
+ "typefest.configs.strict",
6752
+ "typefest.configs.all"
6753
+ ],
6754
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-array-length"
6755
+ },
6756
+ fixable: "code",
6757
+ messages: {
6758
+ preferArrayLength: 'Prefer `ArrayLength<T>` from type-fest over array and tuple `T["length"]` type queries.'
6759
+ },
6760
+ schema: [],
6761
+ type: "suggestion"
6762
+ },
6763
+ name: "prefer-type-fest-array-length"
6764
+ });
6765
+ var prefer_type_fest_array_length_default = preferTypeFestArrayLengthRule;
6766
+
6610
6767
  // dist/_internal/type-reference-node.js
6611
6768
  var isIdentifierTypeReference = (node, identifierName) => node.type === "TSTypeReference" && node.typeName.type === "Identifier" && node.typeName.name === identifierName;
6612
6769
 
@@ -6764,6 +6921,65 @@ var preferTypeFestAsyncReturnTypeRule = createTypedRule({
6764
6921
  });
6765
6922
  var prefer_type_fest_async_return_type_default = preferTypeFestAsyncReturnTypeRule;
6766
6923
 
6924
+ // dist/rules/prefer-type-fest-conditional-pick-deep.js
6925
+ var conditionalPickDeepAliasReplacements = {
6926
+ PickDeepByType: "ConditionalPickDeep",
6927
+ PickDeepByTypes: "ConditionalPickDeep"
6928
+ };
6929
+ var preferTypeFestConditionalPickDeepRule = createTypedRule({
6930
+ create(context) {
6931
+ const importedAliasMatches = collectImportedTypeAliasMatches(context.sourceCode, conditionalPickDeepAliasReplacements);
6932
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
6933
+ return {
6934
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
6935
+ if (node.typeName.type !== "Identifier") {
6936
+ return;
6937
+ }
6938
+ const importedAliasMatch = importedAliasMatches.get(node.typeName.name);
6939
+ if (!importedAliasMatch) {
6940
+ return;
6941
+ }
6942
+ const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, importedAliasMatch.replacementName, typeFestDirectImports);
6943
+ reportWithOptionalFix({
6944
+ context,
6945
+ data: {
6946
+ alias: importedAliasMatch.importedName,
6947
+ replacement: importedAliasMatch.replacementName
6948
+ },
6949
+ fix: aliasReplacementFix,
6950
+ messageId: "preferConditionalPickDeep",
6951
+ node
6952
+ });
6953
+ }
6954
+ };
6955
+ },
6956
+ defaultOptions: [],
6957
+ meta: {
6958
+ deprecated: false,
6959
+ docs: {
6960
+ description: "require TypeFest ConditionalPickDeep over imported aliases such as PickDeepByTypes.",
6961
+ frozen: false,
6962
+ recommended: true,
6963
+ requiresTypeChecking: false,
6964
+ typefestConfigs: [
6965
+ "typefest.configs.recommended",
6966
+ "typefest.configs.strict",
6967
+ "typefest.configs.all",
6968
+ "typefest.configs.type-fest/types"
6969
+ ],
6970
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-pick-deep"
6971
+ },
6972
+ fixable: "code",
6973
+ messages: {
6974
+ preferConditionalPickDeep: "Prefer `{{replacement}}` from type-fest for deep conditional property filtering instead of legacy alias `{{alias}}`."
6975
+ },
6976
+ schema: [],
6977
+ type: "suggestion"
6978
+ },
6979
+ name: "prefer-type-fest-conditional-pick-deep"
6980
+ });
6981
+ var prefer_type_fest_conditional_pick_deep_default = preferTypeFestConditionalPickDeepRule;
6982
+
6767
6983
  // dist/rules/prefer-type-fest-conditional-pick.js
6768
6984
  var conditionalPickAliasReplacements = {
6769
6985
  PickByTypes: "ConditionalPick"
@@ -7453,6 +7669,236 @@ var preferTypeFestKeysOfUnionRule = createTypedRule({
7453
7669
  });
7454
7670
  var prefer_type_fest_keys_of_union_default = preferTypeFestKeysOfUnionRule;
7455
7671
 
7672
+ // dist/rules/prefer-type-fest-less-than-or-equal.js
7673
+ var GREATER_THAN_TYPE_NAME = "GreaterThan";
7674
+ var LESS_THAN_OR_EQUAL_TYPE_NAME = "LessThanOrEqual";
7675
+ var isLiteralBooleanType = (node, expectedBooleanValue) => node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === expectedBooleanValue;
7676
+ var isFalseLiteralType = (node) => isLiteralBooleanType(node, false);
7677
+ var isTrueLiteralType2 = (node) => isLiteralBooleanType(node, true);
7678
+ var preferTypeFestLessThanOrEqualRule = createTypedRule({
7679
+ create(context) {
7680
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7681
+ const greaterThanLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, GREATER_THAN_TYPE_NAME);
7682
+ const typeFestNamespaceImportNames = collectNamespaceImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7683
+ const getComparatorTypeArgumentTexts = (typeReference) => {
7684
+ const typeArguments = typeReference.typeArguments?.params ?? [];
7685
+ const [leftType, rightType] = typeArguments;
7686
+ if (!leftType || !rightType || typeArguments.length !== 2) {
7687
+ return null;
7688
+ }
7689
+ return {
7690
+ leftTypeText: context.sourceCode.getText(leftType),
7691
+ rightTypeText: context.sourceCode.getText(rightType)
7692
+ };
7693
+ };
7694
+ const isGreaterThanTypeReference = (typeReference) => {
7695
+ if (typeReference.typeName.type === "Identifier") {
7696
+ return setContainsValue(greaterThanLocalNames, typeReference.typeName.name);
7697
+ }
7698
+ if (typeReference.typeName.type !== "TSQualifiedName") {
7699
+ return false;
7700
+ }
7701
+ return typeReference.typeName.left.type === "Identifier" && setContainsValue(typeFestNamespaceImportNames, typeReference.typeName.left.name) && typeReference.typeName.right.type === "Identifier" && typeReference.typeName.right.name === GREATER_THAN_TYPE_NAME;
7702
+ };
7703
+ const getComparatorTypeArgumentTextsFromTypeNode = (typeNode) => {
7704
+ if (typeNode.type !== "TSTypeReference") {
7705
+ return null;
7706
+ }
7707
+ if (!isGreaterThanTypeReference(typeNode)) {
7708
+ return null;
7709
+ }
7710
+ return getComparatorTypeArgumentTexts(typeNode);
7711
+ };
7712
+ const getDirectLessThanOrEqualReplacement = (conditionalTypeNode) => {
7713
+ const comparatorTypeArgumentTexts = getComparatorTypeArgumentTextsFromTypeNode(conditionalTypeNode.checkType);
7714
+ if (!comparatorTypeArgumentTexts) {
7715
+ return null;
7716
+ }
7717
+ if (!isTrueLiteralType2(conditionalTypeNode.extendsType) || !isFalseLiteralType(conditionalTypeNode.trueType) || !isTrueLiteralType2(conditionalTypeNode.falseType)) {
7718
+ return null;
7719
+ }
7720
+ return comparatorTypeArgumentTexts;
7721
+ };
7722
+ const getInferWrappedLessThanOrEqualReplacement = (conditionalTypeNode) => {
7723
+ const comparatorTypeArgumentTexts = getComparatorTypeArgumentTextsFromTypeNode(conditionalTypeNode.checkType);
7724
+ if (!comparatorTypeArgumentTexts) {
7725
+ return null;
7726
+ }
7727
+ if (conditionalTypeNode.extendsType.type !== "TSInferType" || conditionalTypeNode.falseType.type !== "TSNeverKeyword" || conditionalTypeNode.trueType.type !== "TSConditionalType") {
7728
+ return null;
7729
+ }
7730
+ const inferIdentifierName = conditionalTypeNode.extendsType.typeParameter.name.name;
7731
+ const innerConditionalTypeNode = conditionalTypeNode.trueType;
7732
+ if (innerConditionalTypeNode.checkType.type !== "TSTypeReference" || innerConditionalTypeNode.checkType.typeName.type !== "Identifier" || innerConditionalTypeNode.checkType.typeName.name !== inferIdentifierName || innerConditionalTypeNode.checkType.typeArguments !== void 0 || !isTrueLiteralType2(innerConditionalTypeNode.extendsType) || !isFalseLiteralType(innerConditionalTypeNode.trueType) || !isTrueLiteralType2(innerConditionalTypeNode.falseType)) {
7733
+ return null;
7734
+ }
7735
+ return comparatorTypeArgumentTexts;
7736
+ };
7737
+ const getLessThanOrEqualReplacementText = (conditionalTypeNode) => {
7738
+ const comparatorTypeArgumentTexts = getDirectLessThanOrEqualReplacement(conditionalTypeNode) ?? getInferWrappedLessThanOrEqualReplacement(conditionalTypeNode);
7739
+ if (!comparatorTypeArgumentTexts) {
7740
+ return null;
7741
+ }
7742
+ return `${LESS_THAN_OR_EQUAL_TYPE_NAME}<${comparatorTypeArgumentTexts.leftTypeText}, ${comparatorTypeArgumentTexts.rightTypeText}>`;
7743
+ };
7744
+ return {
7745
+ TSConditionalType(node) {
7746
+ const replacementText = getLessThanOrEqualReplacementText(node);
7747
+ if (replacementText === null || replacementText.length === 0) {
7748
+ return;
7749
+ }
7750
+ const fix = createSafeTypeNodeTextReplacementFix(node, LESS_THAN_OR_EQUAL_TYPE_NAME, replacementText, typeFestDirectImports);
7751
+ reportWithOptionalFix({
7752
+ context,
7753
+ fix,
7754
+ messageId: "preferLessThanOrEqual",
7755
+ node
7756
+ });
7757
+ }
7758
+ };
7759
+ },
7760
+ defaultOptions: [],
7761
+ meta: {
7762
+ deprecated: false,
7763
+ docs: {
7764
+ description: "require TypeFest LessThanOrEqual over `GreaterThan<A, B> extends true ? false : true` wrappers.",
7765
+ frozen: false,
7766
+ recommended: true,
7767
+ requiresTypeChecking: false,
7768
+ typefestConfigs: [
7769
+ "typefest.configs.recommended",
7770
+ "typefest.configs.strict",
7771
+ "typefest.configs.all",
7772
+ "typefest.configs.type-fest/types"
7773
+ ],
7774
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-less-than-or-equal"
7775
+ },
7776
+ fixable: "code",
7777
+ messages: {
7778
+ preferLessThanOrEqual: "Prefer `LessThanOrEqual<A, B>` from type-fest over wrappers built from `GreaterThan<A, B>`."
7779
+ },
7780
+ schema: [],
7781
+ type: "suggestion"
7782
+ },
7783
+ name: "prefer-type-fest-less-than-or-equal"
7784
+ });
7785
+ var prefer_type_fest_less_than_or_equal_default = preferTypeFestLessThanOrEqualRule;
7786
+
7787
+ // dist/rules/prefer-type-fest-less-than.js
7788
+ var GREATER_THAN_OR_EQUAL_TYPE_NAME = "GreaterThanOrEqual";
7789
+ var LESS_THAN_TYPE_NAME = "LessThan";
7790
+ var isLiteralBooleanType2 = (node, expectedBooleanValue) => node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === expectedBooleanValue;
7791
+ var isFalseLiteralType2 = (node) => isLiteralBooleanType2(node, false);
7792
+ var isTrueLiteralType3 = (node) => isLiteralBooleanType2(node, true);
7793
+ var preferTypeFestLessThanRule = createTypedRule({
7794
+ create(context) {
7795
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7796
+ const greaterThanOrEqualLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, GREATER_THAN_OR_EQUAL_TYPE_NAME);
7797
+ const typeFestNamespaceImportNames = collectNamespaceImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7798
+ const getComparatorTypeArgumentTexts = (typeReference) => {
7799
+ const typeArguments = typeReference.typeArguments?.params ?? [];
7800
+ const [leftType, rightType] = typeArguments;
7801
+ if (!leftType || !rightType || typeArguments.length !== 2) {
7802
+ return null;
7803
+ }
7804
+ return {
7805
+ leftTypeText: context.sourceCode.getText(leftType),
7806
+ rightTypeText: context.sourceCode.getText(rightType)
7807
+ };
7808
+ };
7809
+ const isGreaterThanOrEqualTypeReference = (typeReference) => {
7810
+ if (typeReference.typeName.type === "Identifier") {
7811
+ return setContainsValue(greaterThanOrEqualLocalNames, typeReference.typeName.name);
7812
+ }
7813
+ if (typeReference.typeName.type !== "TSQualifiedName") {
7814
+ return false;
7815
+ }
7816
+ return typeReference.typeName.left.type === "Identifier" && setContainsValue(typeFestNamespaceImportNames, typeReference.typeName.left.name) && typeReference.typeName.right.type === "Identifier" && typeReference.typeName.right.name === GREATER_THAN_OR_EQUAL_TYPE_NAME;
7817
+ };
7818
+ const getComparatorTypeArgumentTextsFromTypeNode = (typeNode) => {
7819
+ if (typeNode.type !== "TSTypeReference") {
7820
+ return null;
7821
+ }
7822
+ if (!isGreaterThanOrEqualTypeReference(typeNode)) {
7823
+ return null;
7824
+ }
7825
+ return getComparatorTypeArgumentTexts(typeNode);
7826
+ };
7827
+ const getDirectLessThanReplacement = (conditionalTypeNode) => {
7828
+ const comparatorTypeArgumentTexts = getComparatorTypeArgumentTextsFromTypeNode(conditionalTypeNode.checkType);
7829
+ if (!comparatorTypeArgumentTexts) {
7830
+ return null;
7831
+ }
7832
+ if (!isTrueLiteralType3(conditionalTypeNode.extendsType) || !isFalseLiteralType2(conditionalTypeNode.trueType) || !isTrueLiteralType3(conditionalTypeNode.falseType)) {
7833
+ return null;
7834
+ }
7835
+ return comparatorTypeArgumentTexts;
7836
+ };
7837
+ const getInferWrappedLessThanReplacement = (conditionalTypeNode) => {
7838
+ const comparatorTypeArgumentTexts = getComparatorTypeArgumentTextsFromTypeNode(conditionalTypeNode.checkType);
7839
+ if (!comparatorTypeArgumentTexts) {
7840
+ return null;
7841
+ }
7842
+ if (conditionalTypeNode.extendsType.type !== "TSInferType" || conditionalTypeNode.falseType.type !== "TSNeverKeyword" || conditionalTypeNode.trueType.type !== "TSConditionalType") {
7843
+ return null;
7844
+ }
7845
+ const inferIdentifierName = conditionalTypeNode.extendsType.typeParameter.name.name;
7846
+ const innerConditionalTypeNode = conditionalTypeNode.trueType;
7847
+ if (innerConditionalTypeNode.checkType.type !== "TSTypeReference" || innerConditionalTypeNode.checkType.typeName.type !== "Identifier" || innerConditionalTypeNode.checkType.typeName.name !== inferIdentifierName || innerConditionalTypeNode.checkType.typeArguments !== void 0 || !isTrueLiteralType3(innerConditionalTypeNode.extendsType) || !isFalseLiteralType2(innerConditionalTypeNode.trueType) || !isTrueLiteralType3(innerConditionalTypeNode.falseType)) {
7848
+ return null;
7849
+ }
7850
+ return comparatorTypeArgumentTexts;
7851
+ };
7852
+ const getLessThanReplacementText = (conditionalTypeNode) => {
7853
+ const comparatorTypeArgumentTexts = getDirectLessThanReplacement(conditionalTypeNode) ?? getInferWrappedLessThanReplacement(conditionalTypeNode);
7854
+ if (!comparatorTypeArgumentTexts) {
7855
+ return null;
7856
+ }
7857
+ return `${LESS_THAN_TYPE_NAME}<${comparatorTypeArgumentTexts.leftTypeText}, ${comparatorTypeArgumentTexts.rightTypeText}>`;
7858
+ };
7859
+ return {
7860
+ TSConditionalType(node) {
7861
+ const replacementText = getLessThanReplacementText(node);
7862
+ if (replacementText === null || replacementText.length === 0) {
7863
+ return;
7864
+ }
7865
+ const fix = createSafeTypeNodeTextReplacementFix(node, LESS_THAN_TYPE_NAME, replacementText, typeFestDirectImports);
7866
+ reportWithOptionalFix({
7867
+ context,
7868
+ fix,
7869
+ messageId: "preferLessThan",
7870
+ node
7871
+ });
7872
+ }
7873
+ };
7874
+ },
7875
+ defaultOptions: [],
7876
+ meta: {
7877
+ deprecated: false,
7878
+ docs: {
7879
+ description: "require TypeFest LessThan over `GreaterThanOrEqual<A, B> extends true ? false : true` wrappers.",
7880
+ frozen: false,
7881
+ recommended: true,
7882
+ requiresTypeChecking: false,
7883
+ typefestConfigs: [
7884
+ "typefest.configs.recommended",
7885
+ "typefest.configs.strict",
7886
+ "typefest.configs.all",
7887
+ "typefest.configs.type-fest/types"
7888
+ ],
7889
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-less-than"
7890
+ },
7891
+ fixable: "code",
7892
+ messages: {
7893
+ preferLessThan: "Prefer `LessThan<A, B>` from type-fest over wrappers built from `GreaterThanOrEqual<A, B>`."
7894
+ },
7895
+ schema: [],
7896
+ type: "suggestion"
7897
+ },
7898
+ name: "prefer-type-fest-less-than"
7899
+ });
7900
+ var prefer_type_fest_less_than_default = preferTypeFestLessThanRule;
7901
+
7456
7902
  // dist/rules/prefer-type-fest-literal-union.js
7457
7903
  var import_ts_extras35 = require("ts-extras");
7458
7904
  var literalUnionFamilies = [
@@ -7778,6 +8224,192 @@ var preferTypeFestOmitIndexSignatureRule = createTypedRule({
7778
8224
  });
7779
8225
  var prefer_type_fest_omit_index_signature_default = preferTypeFestOmitIndexSignatureRule;
7780
8226
 
8227
+ // dist/rules/prefer-type-fest-optional.js
8228
+ var import_ts_extras36 = require("ts-extras");
8229
+ var OPTIONAL_TYPE_NAME = "Optional";
8230
+ var EXCLUDE_TYPE_NAME = "Exclude";
8231
+ var NON_NULLABLE_TYPE_NAME = "NonNullable";
8232
+ var isNullKeywordType = (node) => node.type === "TSNullKeyword";
8233
+ var isUndefinedKeywordType = (node) => node.type === "TSUndefinedKeyword";
8234
+ var isNullishDeleteType = (node) => {
8235
+ if (isNullKeywordType(node)) {
8236
+ return true;
8237
+ }
8238
+ if (node.type !== "TSUnionType" || node.types.length !== 2) {
8239
+ return false;
8240
+ }
8241
+ let hasNull = false;
8242
+ let hasUndefined = false;
8243
+ for (const member of node.types) {
8244
+ if (isNullKeywordType(member)) {
8245
+ hasNull = true;
8246
+ continue;
8247
+ }
8248
+ if (isUndefinedKeywordType(member)) {
8249
+ hasUndefined = true;
8250
+ continue;
8251
+ }
8252
+ return false;
8253
+ }
8254
+ return hasNull && hasUndefined;
8255
+ };
8256
+ var getOptionalInnerTypeText = ({ sourceCode, typeNode }) => {
8257
+ if (typeNode.type !== "TSTypeReference" || typeNode.typeName.type !== "Identifier") {
8258
+ return null;
8259
+ }
8260
+ const typeArguments = typeNode.typeArguments?.params ?? [];
8261
+ if (typeNode.typeName.name === NON_NULLABLE_TYPE_NAME) {
8262
+ const [innerType2] = typeArguments;
8263
+ return innerType2 ? sourceCode.getText(innerType2) : null;
8264
+ }
8265
+ if (typeNode.typeName.name !== EXCLUDE_TYPE_NAME) {
8266
+ return null;
8267
+ }
8268
+ const [innerType, deletedType] = typeArguments;
8269
+ if (!innerType || !deletedType || !isNullishDeleteType(deletedType)) {
8270
+ return null;
8271
+ }
8272
+ return sourceCode.getText(innerType);
8273
+ };
8274
+ var preferTypeFestOptionalRule = createTypedRule({
8275
+ create(context) {
8276
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
8277
+ return {
8278
+ TSUnionType(node) {
8279
+ if (node.types.length !== 2) {
8280
+ return;
8281
+ }
8282
+ const firstMember = (0, import_ts_extras36.arrayFirst)(node.types);
8283
+ const secondMember = (0, import_ts_extras36.arrayAt)(node.types, 1);
8284
+ if (!firstMember || !secondMember) {
8285
+ return;
8286
+ }
8287
+ const optionalEquivalentMember = isUndefinedKeywordType(firstMember) ? secondMember : isUndefinedKeywordType(secondMember) ? firstMember : null;
8288
+ if (!optionalEquivalentMember) {
8289
+ return;
8290
+ }
8291
+ const innerTypeText = getOptionalInnerTypeText({
8292
+ sourceCode: context.sourceCode,
8293
+ typeNode: optionalEquivalentMember
8294
+ });
8295
+ if (innerTypeText === null || innerTypeText.trim().length === 0) {
8296
+ return;
8297
+ }
8298
+ const fix = createSafeTypeNodeTextReplacementFix(node, OPTIONAL_TYPE_NAME, `${OPTIONAL_TYPE_NAME}<${innerTypeText}>`, typeFestDirectImports);
8299
+ reportWithOptionalFix({
8300
+ context,
8301
+ fix,
8302
+ messageId: "preferOptional",
8303
+ node
8304
+ });
8305
+ }
8306
+ };
8307
+ },
8308
+ defaultOptions: [],
8309
+ meta: {
8310
+ deprecated: false,
8311
+ docs: {
8312
+ description: "require TypeFest Optional over `Exclude<T, null> | undefined` and `NonNullable<T> | undefined` patterns.",
8313
+ frozen: false,
8314
+ recommended: true,
8315
+ requiresTypeChecking: false,
8316
+ typefestConfigs: [
8317
+ "typefest.configs.recommended",
8318
+ "typefest.configs.strict",
8319
+ "typefest.configs.all",
8320
+ "typefest.configs.type-fest/types"
8321
+ ],
8322
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-optional"
8323
+ },
8324
+ fixable: "code",
8325
+ messages: {
8326
+ preferOptional: "Prefer `Optional<T>` from type-fest over `Exclude<T, null> | undefined` and equivalent optional-value patterns."
8327
+ },
8328
+ schema: [],
8329
+ type: "suggestion"
8330
+ },
8331
+ name: "prefer-type-fest-optional"
8332
+ });
8333
+ var prefer_type_fest_optional_default = preferTypeFestOptionalRule;
8334
+
8335
+ // dist/rules/prefer-type-fest-or-all.js
8336
+ var SOME_EXTEND_TYPE_NAME = "SomeExtend";
8337
+ var OR_ALL_TYPE_NAME = "OrAll";
8338
+ var isTrueLiteralType4 = (node) => node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === true;
8339
+ var preferTypeFestOrAllRule = createTypedRule({
8340
+ create(context) {
8341
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
8342
+ const someExtendLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, SOME_EXTEND_TYPE_NAME);
8343
+ const typeFestNamespaceImportNames = collectNamespaceImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
8344
+ const getSomeExtendTupleArgumentText = (typeReference) => {
8345
+ const typeArguments = typeReference.typeArguments?.params ?? [];
8346
+ const [tupleArgument, comparedType] = typeArguments;
8347
+ if (!tupleArgument || !comparedType || !isTrueLiteralType4(comparedType)) {
8348
+ return null;
8349
+ }
8350
+ if (typeArguments.length !== 2) {
8351
+ return null;
8352
+ }
8353
+ return context.sourceCode.getText(tupleArgument);
8354
+ };
8355
+ const reportIfSomeExtendEquivalent = (node) => {
8356
+ const tupleArgumentText = getSomeExtendTupleArgumentText(node);
8357
+ if (tupleArgumentText === null || tupleArgumentText.trim().length === 0) {
8358
+ return;
8359
+ }
8360
+ const fix = createSafeTypeNodeTextReplacementFix(node, OR_ALL_TYPE_NAME, `${OR_ALL_TYPE_NAME}<${tupleArgumentText}>`, typeFestDirectImports);
8361
+ reportWithOptionalFix({
8362
+ context,
8363
+ fix,
8364
+ messageId: "preferOrAll",
8365
+ node
8366
+ });
8367
+ };
8368
+ return {
8369
+ 'TSTypeReference[typeName.type="Identifier"]'(typeReference) {
8370
+ if (typeReference.typeName.type !== "Identifier" || !setContainsValue(someExtendLocalNames, typeReference.typeName.name)) {
8371
+ return;
8372
+ }
8373
+ reportIfSomeExtendEquivalent(typeReference);
8374
+ },
8375
+ 'TSTypeReference[typeName.type="TSQualifiedName"]'(typeReference) {
8376
+ if (typeReference.typeName.type !== "TSQualifiedName") {
8377
+ return;
8378
+ }
8379
+ if (typeReference.typeName.left.type !== "Identifier" || !setContainsValue(typeFestNamespaceImportNames, typeReference.typeName.left.name) || typeReference.typeName.right.type !== "Identifier" || typeReference.typeName.right.name !== SOME_EXTEND_TYPE_NAME) {
8380
+ return;
8381
+ }
8382
+ reportIfSomeExtendEquivalent(typeReference);
8383
+ }
8384
+ };
8385
+ },
8386
+ defaultOptions: [],
8387
+ meta: {
8388
+ deprecated: false,
8389
+ docs: {
8390
+ description: "require TypeFest OrAll over `SomeExtend<TTuple, true>` boolean-tuple checks.",
8391
+ frozen: false,
8392
+ recommended: true,
8393
+ requiresTypeChecking: false,
8394
+ typefestConfigs: [
8395
+ "typefest.configs.recommended",
8396
+ "typefest.configs.strict",
8397
+ "typefest.configs.all",
8398
+ "typefest.configs.type-fest/types"
8399
+ ],
8400
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-or-all"
8401
+ },
8402
+ fixable: "code",
8403
+ messages: {
8404
+ preferOrAll: "Prefer `OrAll<TTuple>` from type-fest over `SomeExtend<TTuple, true>` for boolean-tuple disjunction checks."
8405
+ },
8406
+ schema: [],
8407
+ type: "suggestion"
8408
+ },
8409
+ name: "prefer-type-fest-or-all"
8410
+ });
8411
+ var prefer_type_fest_or_all_default = preferTypeFestOrAllRule;
8412
+
7781
8413
  // dist/rules/prefer-type-fest-partial-deep.js
7782
8414
  var preferTypeFestPartialDeepRule = createTypedRule({
7783
8415
  create(context) {
@@ -7897,7 +8529,7 @@ var preferTypeFestPrimitiveRule = createTypedRule({
7897
8529
  var prefer_type_fest_primitive_default = preferTypeFestPrimitiveRule;
7898
8530
 
7899
8531
  // dist/rules/prefer-type-fest-promisable.js
7900
- var import_ts_extras36 = require("ts-extras");
8532
+ var import_ts_extras37 = require("ts-extras");
7901
8533
  var PROMISABLE_TYPE_NAME = "Promisable";
7902
8534
  var PROMISE_TYPE_NAME = "Promise";
7903
8535
  var promisableAliasReplacements = {
@@ -7913,10 +8545,10 @@ var getPromiseInnerType = (node) => {
7913
8545
  return null;
7914
8546
  }
7915
8547
  const typeArguments = node.typeArguments?.params;
7916
- if (!(0, import_ts_extras36.isDefined)(typeArguments)) {
8548
+ if (!(0, import_ts_extras37.isDefined)(typeArguments)) {
7917
8549
  return null;
7918
8550
  }
7919
- return (0, import_ts_extras36.arrayFirst)(typeArguments) ?? null;
8551
+ return (0, import_ts_extras37.arrayFirst)(typeArguments) ?? null;
7920
8552
  };
7921
8553
  var preferTypeFestPromisableRule = createTypedRule({
7922
8554
  create(context, [options] = defaultOptions3) {
@@ -8977,6 +9609,195 @@ var preferTypeFestTupleOfRule = createTypedRule({
8977
9609
  });
8978
9610
  var prefer_type_fest_tuple_of_default = preferTypeFestTupleOfRule;
8979
9611
 
9612
+ // dist/rules/prefer-type-fest-union-member.js
9613
+ var import_ts_extras38 = require("ts-extras");
9614
+ var UNION_MEMBER_TYPE_NAME = "UnionMember";
9615
+ var UNION_TO_INTERSECTION_TYPE_NAME = "UnionToIntersection";
9616
+ var IS_NEVER_TYPE_NAME = "IsNever";
9617
+ var isIdentifierTypeReferenceNamed = (node, name) => node.type === "TSTypeReference" && node.typeName.type === "Identifier" && node.typeName.name === name;
9618
+ var isBooleanLiteralType = (node, expectedValue) => node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === expectedValue;
9619
+ var getUnionArgumentTextFromDistributiveFunctionWrapper = ({ node, sourceCode }) => {
9620
+ if (node.type !== "TSConditionalType") {
9621
+ return null;
9622
+ }
9623
+ if (node.extendsType.type !== "TSAnyKeyword" || node.falseType.type !== "TSNeverKeyword") {
9624
+ return null;
9625
+ }
9626
+ if (node.trueType.type !== "TSFunctionType") {
9627
+ return null;
9628
+ }
9629
+ const returnType = node.trueType.returnType?.typeAnnotation;
9630
+ if (!returnType) {
9631
+ return null;
9632
+ }
9633
+ const checkTypeText = sourceCode.getText(node.checkType);
9634
+ const returnTypeText = sourceCode.getText(returnType);
9635
+ return checkTypeText === returnTypeText ? checkTypeText : null;
9636
+ };
9637
+ var getUnionArgumentTextFromExtractor = ({ node, sourceCode }) => {
9638
+ if (node.falseType.type !== "TSNeverKeyword") {
9639
+ return null;
9640
+ }
9641
+ if (!isIdentifierTypeReferenceNamed(node.checkType, UNION_TO_INTERSECTION_TYPE_NAME)) {
9642
+ return null;
9643
+ }
9644
+ const extractorArgument = (0, import_ts_extras38.arrayFirst)(node.checkType.typeArguments?.params ?? []);
9645
+ if (!extractorArgument) {
9646
+ return null;
9647
+ }
9648
+ const unionArgumentText = getUnionArgumentTextFromDistributiveFunctionWrapper({
9649
+ node: extractorArgument,
9650
+ sourceCode
9651
+ });
9652
+ if (unionArgumentText === null) {
9653
+ return null;
9654
+ }
9655
+ if (node.extendsType.type !== "TSFunctionType") {
9656
+ return null;
9657
+ }
9658
+ const inferredReturnType = node.extendsType.returnType?.typeAnnotation;
9659
+ const inferredTypeParameterName = inferredReturnType?.type === "TSInferType" ? inferredReturnType.typeParameter.name.name : null;
9660
+ if (inferredTypeParameterName === null || node.trueType.type !== "TSTypeReference" || node.trueType.typeName.type !== "Identifier" || node.trueType.typeName.name !== inferredTypeParameterName) {
9661
+ return null;
9662
+ }
9663
+ return unionArgumentText;
9664
+ };
9665
+ var getUnionMemberEquivalentArgumentText = ({ node, sourceCode }) => {
9666
+ if (node.type !== "TSConditionalType") {
9667
+ return null;
9668
+ }
9669
+ const directExtractorText = getUnionArgumentTextFromExtractor({
9670
+ node,
9671
+ sourceCode
9672
+ });
9673
+ if (directExtractorText !== null) {
9674
+ return directExtractorText;
9675
+ }
9676
+ if (!isIdentifierTypeReferenceNamed(node.checkType, IS_NEVER_TYPE_NAME) || !isBooleanLiteralType(node.extendsType, true) || node.trueType.type !== "TSNeverKeyword") {
9677
+ return null;
9678
+ }
9679
+ const guardedArgument = (0, import_ts_extras38.arrayFirst)(node.checkType.typeArguments?.params ?? []);
9680
+ if (!guardedArgument) {
9681
+ return null;
9682
+ }
9683
+ const guardedArgumentText = sourceCode.getText(guardedArgument);
9684
+ if (node.falseType.type !== "TSConditionalType") {
9685
+ return null;
9686
+ }
9687
+ const extractorText = getUnionArgumentTextFromExtractor({
9688
+ node: node.falseType,
9689
+ sourceCode
9690
+ });
9691
+ return extractorText === guardedArgumentText ? extractorText : null;
9692
+ };
9693
+ var preferTypeFestUnionMemberRule = createTypedRule({
9694
+ create(context) {
9695
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
9696
+ return {
9697
+ TSTypeAliasDeclaration(node) {
9698
+ const unionArgumentText = getUnionMemberEquivalentArgumentText({
9699
+ node: node.typeAnnotation,
9700
+ sourceCode: context.sourceCode
9701
+ });
9702
+ if (unionArgumentText === null || unionArgumentText.trim().length === 0) {
9703
+ return;
9704
+ }
9705
+ const fix = createSafeTypeNodeTextReplacementFix(node.typeAnnotation, UNION_MEMBER_TYPE_NAME, `${UNION_MEMBER_TYPE_NAME}<${unionArgumentText}>`, typeFestDirectImports);
9706
+ reportWithOptionalFix({
9707
+ context,
9708
+ fix,
9709
+ messageId: "preferUnionMember",
9710
+ node: node.typeAnnotation
9711
+ });
9712
+ }
9713
+ };
9714
+ },
9715
+ defaultOptions: [],
9716
+ meta: {
9717
+ deprecated: false,
9718
+ docs: {
9719
+ description: "require TypeFest UnionMember over custom union-member extraction helpers based on `UnionToIntersection`.",
9720
+ frozen: false,
9721
+ recommended: true,
9722
+ requiresTypeChecking: false,
9723
+ typefestConfigs: [
9724
+ "typefest.configs.recommended",
9725
+ "typefest.configs.strict",
9726
+ "typefest.configs.all",
9727
+ "typefest.configs.type-fest/types"
9728
+ ],
9729
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-union-member"
9730
+ },
9731
+ fixable: "code",
9732
+ messages: {
9733
+ preferUnionMember: "Prefer `UnionMember<T>` from type-fest over custom union-member extraction helpers based on `UnionToIntersection`."
9734
+ },
9735
+ schema: [],
9736
+ type: "suggestion"
9737
+ },
9738
+ name: "prefer-type-fest-union-member"
9739
+ });
9740
+ var prefer_type_fest_union_member_default = preferTypeFestUnionMemberRule;
9741
+
9742
+ // dist/rules/prefer-type-fest-union-to-tuple.js
9743
+ var unionToTupleAliasReplacements = {
9744
+ TupleFromUnion: "UnionToTuple",
9745
+ TuplifyUnion: "UnionToTuple"
9746
+ };
9747
+ var preferTypeFestUnionToTupleRule = createTypedRule({
9748
+ create(context) {
9749
+ const importedAliasMatches = collectImportedTypeAliasMatches(context.sourceCode, unionToTupleAliasReplacements);
9750
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
9751
+ return {
9752
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
9753
+ if (node.typeName.type !== "Identifier") {
9754
+ return;
9755
+ }
9756
+ const importedAliasMatch = importedAliasMatches.get(node.typeName.name);
9757
+ if (!importedAliasMatch) {
9758
+ return;
9759
+ }
9760
+ const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, importedAliasMatch.replacementName, typeFestDirectImports);
9761
+ reportWithOptionalFix({
9762
+ context,
9763
+ data: {
9764
+ alias: importedAliasMatch.importedName,
9765
+ replacement: importedAliasMatch.replacementName
9766
+ },
9767
+ fix: aliasReplacementFix,
9768
+ messageId: "preferUnionToTuple",
9769
+ node
9770
+ });
9771
+ }
9772
+ };
9773
+ },
9774
+ defaultOptions: [],
9775
+ meta: {
9776
+ deprecated: false,
9777
+ docs: {
9778
+ description: "require TypeFest UnionToTuple over imported aliases such as TuplifyUnion.",
9779
+ frozen: false,
9780
+ recommended: true,
9781
+ requiresTypeChecking: false,
9782
+ typefestConfigs: [
9783
+ "typefest.configs.recommended",
9784
+ "typefest.configs.strict",
9785
+ "typefest.configs.all",
9786
+ "typefest.configs.type-fest/types"
9787
+ ],
9788
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-union-to-tuple"
9789
+ },
9790
+ fixable: "code",
9791
+ messages: {
9792
+ preferUnionToTuple: "Prefer `{{replacement}}` from type-fest to convert unions into tuple forms instead of legacy alias `{{alias}}`."
9793
+ },
9794
+ schema: [],
9795
+ type: "suggestion"
9796
+ },
9797
+ name: "prefer-type-fest-union-to-tuple"
9798
+ });
9799
+ var prefer_type_fest_union_to_tuple_default = preferTypeFestUnionToTupleRule;
9800
+
8980
9801
  // dist/rules/prefer-type-fest-unknown-array.js
8981
9802
  var READONLY_ARRAY_TYPE_NAME2 = "ReadonlyArray";
8982
9803
  var UNKNOWN_ARRAY_TYPE_NAME = "UnknownArray";
@@ -9530,9 +10351,12 @@ var typefestRuleRegistry = {
9530
10351
  "prefer-ts-extras-set-has": prefer_ts_extras_set_has_default,
9531
10352
  "prefer-ts-extras-string-split": prefer_ts_extras_string_split_default,
9532
10353
  "prefer-type-fest-abstract-constructor": prefer_type_fest_abstract_constructor_default,
10354
+ "prefer-type-fest-and-all": prefer_type_fest_and_all_default,
10355
+ "prefer-type-fest-array-length": prefer_type_fest_array_length_default,
9533
10356
  "prefer-type-fest-arrayable": prefer_type_fest_arrayable_default,
9534
10357
  "prefer-type-fest-async-return-type": prefer_type_fest_async_return_type_default,
9535
10358
  "prefer-type-fest-conditional-pick": prefer_type_fest_conditional_pick_default,
10359
+ "prefer-type-fest-conditional-pick-deep": prefer_type_fest_conditional_pick_deep_default,
9536
10360
  "prefer-type-fest-constructor": prefer_type_fest_constructor_default,
9537
10361
  "prefer-type-fest-except": prefer_type_fest_except_default,
9538
10362
  "prefer-type-fest-if": prefer_type_fest_if_default,
@@ -9542,10 +10366,14 @@ var typefestRuleRegistry = {
9542
10366
  "prefer-type-fest-json-primitive": prefer_type_fest_json_primitive_default,
9543
10367
  "prefer-type-fest-json-value": prefer_type_fest_json_value_default,
9544
10368
  "prefer-type-fest-keys-of-union": prefer_type_fest_keys_of_union_default,
10369
+ "prefer-type-fest-less-than": prefer_type_fest_less_than_default,
10370
+ "prefer-type-fest-less-than-or-equal": prefer_type_fest_less_than_or_equal_default,
9545
10371
  "prefer-type-fest-literal-union": prefer_type_fest_literal_union_default,
9546
10372
  "prefer-type-fest-merge-exclusive": prefer_type_fest_merge_exclusive_default,
9547
10373
  "prefer-type-fest-non-empty-tuple": prefer_type_fest_non_empty_tuple_default,
9548
10374
  "prefer-type-fest-omit-index-signature": prefer_type_fest_omit_index_signature_default,
10375
+ "prefer-type-fest-optional": prefer_type_fest_optional_default,
10376
+ "prefer-type-fest-or-all": prefer_type_fest_or_all_default,
9549
10377
  "prefer-type-fest-partial-deep": prefer_type_fest_partial_deep_default,
9550
10378
  "prefer-type-fest-primitive": prefer_type_fest_primitive_default,
9551
10379
  "prefer-type-fest-promisable": prefer_type_fest_promisable_default,
@@ -9563,6 +10391,8 @@ var typefestRuleRegistry = {
9563
10391
  "prefer-type-fest-simplify": prefer_type_fest_simplify_default,
9564
10392
  "prefer-type-fest-tagged-brands": prefer_type_fest_tagged_brands_default,
9565
10393
  "prefer-type-fest-tuple-of": prefer_type_fest_tuple_of_default,
10394
+ "prefer-type-fest-union-member": prefer_type_fest_union_member_default,
10395
+ "prefer-type-fest-union-to-tuple": prefer_type_fest_union_to_tuple_default,
9566
10396
  "prefer-type-fest-unknown-array": prefer_type_fest_unknown_array_default,
9567
10397
  "prefer-type-fest-unknown-map": prefer_type_fest_unknown_map_default,
9568
10398
  "prefer-type-fest-unknown-record": prefer_type_fest_unknown_record_default,
@@ -9584,7 +10414,7 @@ function getPackageVersion(pkg) {
9584
10414
  const version = Reflect.get(pkg, "version");
9585
10415
  return typeof version === "string" ? version : "0.0.0";
9586
10416
  }
9587
- var packageJsonValue = (0, import_ts_extras37.safeCastTo)(package_default);
10417
+ var packageJsonValue = (0, import_ts_extras39.safeCastTo)(package_default);
9588
10418
  var typeScriptParserValue = import_parser3.default;
9589
10419
  var defaultParserOptions = {
9590
10420
  ecmaVersion: "latest",
@@ -9592,10 +10422,10 @@ var defaultParserOptions = {
9592
10422
  };
9593
10423
  var normalizeParserOptions = (parserOptions) => parserOptions !== null && typeof parserOptions === "object" && !Array.isArray(parserOptions) ? { ...parserOptions } : { ...defaultParserOptions };
9594
10424
  var typefestEslintRules = typefestRules;
9595
- var isTypefestRuleName = (value) => (0, import_ts_extras37.objectHasIn)(typefestRules, value);
10425
+ var isTypefestRuleName = (value) => (0, import_ts_extras39.objectHasIn)(typefestRules, value);
9596
10426
  var typefestRuleEntries = (() => {
9597
10427
  const entries = [];
9598
- for (const [ruleName] of (0, import_ts_extras37.objectEntries)(typefestRules)) {
10428
+ for (const [ruleName] of (0, import_ts_extras39.objectEntries)(typefestRules)) {
9599
10429
  if (!isTypefestRuleName(ruleName)) {
9600
10430
  continue;
9601
10431
  }
@@ -9622,7 +10452,7 @@ var derivePresetRuleNamesByConfig = () => {
9622
10452
  const presetRuleNamesByConfig2 = createEmptyPresetRuleMap();
9623
10453
  for (const [ruleName] of typefestRuleEntries) {
9624
10454
  const configNames = rulePresetMembership[ruleName];
9625
- if (!(0, import_ts_extras37.isDefined)(configNames) || (0, import_ts_extras37.isEmpty)(configNames)) {
10455
+ if (!(0, import_ts_extras39.isDefined)(configNames) || (0, import_ts_extras39.isEmpty)(configNames)) {
9626
10456
  throw new TypeError(`Rule '${ruleName}' is missing preset membership metadata.`);
9627
10457
  }
9628
10458
  for (const configName of configNames) {
@@ -9649,7 +10479,7 @@ function errorRulesFor(ruleNames) {
9649
10479
  var presetRuleNamesByConfig = derivePresetRuleNamesByConfig();
9650
10480
  var recommendedRuleNames = [];
9651
10481
  for (const ruleName of presetRuleNamesByConfig.recommended) {
9652
- if ((0, import_ts_extras37.setHas)(typeCheckedRuleNames, ruleName)) {
10482
+ if ((0, import_ts_extras39.setHas)(typeCheckedRuleNames, ruleName)) {
9653
10483
  continue;
9654
10484
  }
9655
10485
  recommendedRuleNames.push(ruleName);
@@ -9667,7 +10497,7 @@ function withTypefestPlugin(config, plugin, options) {
9667
10497
  const existingLanguageOptions = config.languageOptions ?? {};
9668
10498
  const existingParserOptions = existingLanguageOptions["parserOptions"];
9669
10499
  const parserOptions = normalizeParserOptions(existingParserOptions);
9670
- if (options.requiresTypeChecking && !(0, import_ts_extras37.objectHasIn)(parserOptions, "projectService")) {
10500
+ if (options.requiresTypeChecking && !(0, import_ts_extras39.objectHasIn)(parserOptions, "projectService")) {
9671
10501
  Reflect.set(parserOptions, "projectService", true);
9672
10502
  }
9673
10503
  const languageOptions = {