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
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_extras39 = require("ts-extras");
37
+ var import_ts_extras41 = 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.6",
43
+ version: "1.0.7",
44
44
  private: false,
45
45
  description: "ESLint rules for adopting type-fest and ts-extras conventions.",
46
46
  keywords: [
@@ -254,10 +254,10 @@ var package_default = {
254
254
  "jsonc-eslint-parser": "$jsonc-eslint-parser"
255
255
  },
256
256
  dependencies: {
257
- "@typescript-eslint/parser": "^8.57.1",
258
- "@typescript-eslint/type-utils": "^8.57.1",
259
- "@typescript-eslint/utils": "^8.57.1",
260
- "ts-extras": "^0.17.0",
257
+ "@typescript-eslint/parser": "^8.57.2",
258
+ "@typescript-eslint/type-utils": "^8.57.2",
259
+ "@typescript-eslint/utils": "^8.57.2",
260
+ "ts-extras": "^0.19.0",
261
261
  "type-fest": "^5.5.0"
262
262
  },
263
263
  devDependencies: {
@@ -265,7 +265,7 @@ var package_default = {
265
265
  "@csstools/stylelint-formatter-github": "^2.0.0",
266
266
  "@docusaurus/eslint-plugin": "^3.9.2",
267
267
  "@double-great/remark-lint-alt-text": "^1.1.1",
268
- "@double-great/stylelint-a11y": "^3.4.6",
268
+ "@double-great/stylelint-a11y": "^3.4.7",
269
269
  "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1",
270
270
  "@eslint-react/eslint-plugin": "^3.0.0",
271
271
  "@eslint/compat": "^2.0.3",
@@ -315,11 +315,11 @@ var package_default = {
315
315
  "@types/postcss-normalize": "^9.0.4",
316
316
  "@types/postcss-reporter": "^7.0.5",
317
317
  "@types/sloc": "^0.2.3",
318
- "@typescript-eslint/eslint-plugin": "^8.57.1",
319
- "@typescript-eslint/rule-tester": "^8.57.1",
320
- "@vitest/coverage-v8": "^4.1.0",
321
- "@vitest/eslint-plugin": "^1.6.12",
322
- "@vitest/ui": "^4.1.0",
318
+ "@typescript-eslint/eslint-plugin": "^8.57.2",
319
+ "@typescript-eslint/rule-tester": "^8.57.2",
320
+ "@vitest/coverage-v8": "^4.1.1",
321
+ "@vitest/eslint-plugin": "^1.6.13",
322
+ "@vitest/ui": "^4.1.1",
323
323
  actionlint: "^2.0.6",
324
324
  "all-contributors-cli": "^6.26.1",
325
325
  "cognitive-complexity-ts": "^0.8.1",
@@ -329,7 +329,7 @@ var package_default = {
329
329
  depcheck: "^1.4.7",
330
330
  "detect-secrets": "^1.0.6",
331
331
  eslint: "^10.1.0",
332
- "eslint-config-flat-gitignore": "^2.2.1",
332
+ "eslint-config-flat-gitignore": "^2.3.0",
333
333
  "eslint-config-prettier": "^10.1.8",
334
334
  "eslint-formatter-unix": "^9.0.1",
335
335
  "eslint-import-resolver-typescript": "^4.4.4",
@@ -345,20 +345,19 @@ var package_default = {
345
345
  "eslint-plugin-etc": "^2.0.3",
346
346
  "eslint-plugin-etc-misc": "^1.0.4",
347
347
  "eslint-plugin-file-progress-2": "^3.4.3",
348
+ "eslint-plugin-github-actions-2": "^1.0.0",
348
349
  "eslint-plugin-html": "^8.1.4",
349
- "eslint-plugin-immutable-2": "^1.0.5",
350
+ "eslint-plugin-immutable-2": "^1.0.6",
350
351
  "eslint-plugin-import-x": "^4.16.2",
351
352
  "eslint-plugin-jsdoc": "^62.8.0",
352
353
  "eslint-plugin-jsonc": "^3.1.2",
353
354
  "eslint-plugin-jsx-a11y": "^6.10.2",
354
355
  "eslint-plugin-listeners": "^1.5.1",
355
- "eslint-plugin-loadable-imports": "^1.0.1",
356
356
  "eslint-plugin-math": "^0.13.1",
357
357
  "eslint-plugin-module-interop": "^0.3.1",
358
358
  "eslint-plugin-n": "^17.24.0",
359
359
  "eslint-plugin-nitpick": "^0.12.0",
360
360
  "eslint-plugin-no-barrel-files": "^1.2.2",
361
- "eslint-plugin-no-explicit-type-exports": "^0.12.1",
362
361
  "eslint-plugin-no-function-declare-after-return": "^1.1.0",
363
362
  "eslint-plugin-no-lookahead-lookbehind-regexp": "^0.4.0",
364
363
  "eslint-plugin-no-only-tests": "^3.3.0",
@@ -368,7 +367,6 @@ var package_default = {
368
367
  "eslint-plugin-node-dependencies": "^2.2.0",
369
368
  "eslint-plugin-package-json": "^0.91.0",
370
369
  "eslint-plugin-perfectionist": "^5.7.0",
371
- "eslint-plugin-prefer-arrow": "^1.2.3",
372
370
  "eslint-plugin-prettier": "^5.5.5",
373
371
  "eslint-plugin-promise": "^7.2.1",
374
372
  "eslint-plugin-redos": "^4.5.0",
@@ -378,12 +376,12 @@ var package_default = {
378
376
  "eslint-plugin-security": "^4.0.0",
379
377
  "eslint-plugin-sonarjs": "^4.0.2",
380
378
  "eslint-plugin-sort-class-members": "^1.21.0",
381
- "eslint-plugin-testing-library": "^7.16.1",
379
+ "eslint-plugin-testing-library": "^7.16.2",
382
380
  "eslint-plugin-toml": "^1.3.1",
383
381
  "eslint-plugin-total-functions": "^7.1.0",
384
382
  "eslint-plugin-tsdoc": "^0.5.2",
385
383
  "eslint-plugin-tsdoc-require-2": "^1.0.6",
386
- "eslint-plugin-typefest": "^1.0.5",
384
+ "eslint-plugin-typefest": "^1.0.6",
387
385
  "eslint-plugin-undefined-css-classes": "^0.1.5",
388
386
  "eslint-plugin-unicorn": "^63.0.0",
389
387
  "eslint-plugin-unused-imports": "^4.4.1",
@@ -398,7 +396,7 @@ var package_default = {
398
396
  htmlhint: "^1.9.2",
399
397
  jscpd: "^4.0.8",
400
398
  "jsonc-eslint-parser": "^3.1.0",
401
- knip: "^6.0.1",
399
+ knip: "^6.0.4",
402
400
  leasot: "^14.4.0",
403
401
  madge: "^8.0.0",
404
402
  "markdown-link-check": "^3.14.2",
@@ -418,7 +416,7 @@ var package_default = {
418
416
  "postcss-reporter": "^7.1.0",
419
417
  "postcss-round-subpixels": "^2.0.0",
420
418
  "postcss-scss": "^4.0.9",
421
- "postcss-sort-media-queries": "^6.3.2",
419
+ "postcss-sort-media-queries": "^6.3.3",
422
420
  "postcss-styled-jsx": "^1.0.1",
423
421
  "postcss-styled-syntax": "^0.7.1",
424
422
  "postcss-viewport-height-correction": "^1.1.1",
@@ -576,7 +574,7 @@ var package_default = {
576
574
  "stylelint-order": "^8.1.1",
577
575
  "stylelint-plugin-defensive-css": "^2.8.0",
578
576
  "stylelint-plugin-logical-css": "^2.0.2",
579
- "stylelint-plugin-use-baseline": "^1.4.0",
577
+ "stylelint-plugin-use-baseline": "^1.4.1",
580
578
  "stylelint-prettier": "^5.0.3",
581
579
  "stylelint-react-native": "^2.7.0",
582
580
  "stylelint-scales": "^5.0.0",
@@ -585,20 +583,20 @@ var package_default = {
585
583
  "stylelint-value-no-unknown-custom-properties": "^6.1.1",
586
584
  "toml-eslint-parser": "^1.0.3",
587
585
  "ts-unused-exports": "^11.0.1",
588
- typedoc: "^0.28.17",
589
- typescript: "^5.9.3",
590
- "typescript-eslint": "^8.57.1",
586
+ typedoc: "^0.28.18",
587
+ typescript: "^6.0.2",
588
+ "typescript-eslint": "^8.57.2",
591
589
  typesync: "^0.14.3",
592
590
  vfile: "^6.0.3",
593
- vite: "^8.0.1",
591
+ vite: "^8.0.2",
594
592
  "vite-tsconfig-paths": "^6.1.1",
595
- vitest: "^4.1.0",
593
+ vitest: "^4.1.1",
596
594
  "yaml-eslint-parser": "^2.0.0",
597
595
  "yamllint-js": "^0.2.4"
598
596
  },
599
597
  peerDependencies: {
600
598
  eslint: "^9.0.0 || ^10.1.0",
601
- typescript: ">=5.0.0"
599
+ typescript: "^5.0.0 || ^6.0.0"
602
600
  },
603
601
  packageManager: "npm@11.12.0",
604
602
  engines: {
@@ -634,6 +632,7 @@ var createRuleDocsUrl = (ruleName) => `${RULE_DOCS_URL_BASE}${ruleName}`;
634
632
  var import_ts_extras = require("ts-extras");
635
633
  var typefestConfigNames = [
636
634
  "all",
635
+ "experimental",
637
636
  "minimal",
638
637
  "recommended",
639
638
  "recommended-type-checked",
@@ -648,6 +647,12 @@ var typefestConfigMetadataByName = {
648
647
  readmeOrder: 5,
649
648
  requiresTypeChecking: true
650
649
  },
650
+ experimental: {
651
+ icon: "\u{1F9EA}",
652
+ presetName: "typefest:experimental",
653
+ readmeOrder: 6,
654
+ requiresTypeChecking: true
655
+ },
651
656
  minimal: {
652
657
  icon: "\u{1F7E2}",
653
658
  presetName: "typefest:minimal",
@@ -675,18 +680,19 @@ var typefestConfigMetadataByName = {
675
680
  "ts-extras/type-guards": {
676
681
  icon: "\u2734\uFE0F",
677
682
  presetName: "typefest:ts-extras/type-guards",
678
- readmeOrder: 7,
683
+ readmeOrder: 8,
679
684
  requiresTypeChecking: true
680
685
  },
681
686
  "type-fest/types": {
682
687
  icon: "\u{1F4A0}",
683
688
  presetName: "typefest:type-fest/types",
684
- readmeOrder: 6,
689
+ readmeOrder: 7,
685
690
  requiresTypeChecking: false
686
691
  }
687
692
  };
688
693
  var typefestConfigReferenceToName = {
689
694
  "typefest.configs.all": "all",
695
+ "typefest.configs.experimental": "experimental",
690
696
  "typefest.configs.minimal": "minimal",
691
697
  "typefest.configs.recommended": "recommended",
692
698
  "typefest.configs.recommended-type-checked": "recommended-type-checked",
@@ -1865,6 +1871,24 @@ function getSafeLocalNameForImportedValueInScope({ importedName, imports, source
1865
1871
  }
1866
1872
  return null;
1867
1873
  }
1874
+ var getSafeLocalNameForImportedValue = ({ context, importedName, imports, referenceNode, sourceModuleName }) => {
1875
+ const sourceScope = resolveReferenceScope({
1876
+ context,
1877
+ referenceNode
1878
+ });
1879
+ if (sourceScope === null) {
1880
+ return getFirstImportedAliasName({
1881
+ importedName,
1882
+ imports
1883
+ });
1884
+ }
1885
+ return getSafeLocalNameForImportedValueInScope({
1886
+ importedName,
1887
+ imports,
1888
+ sourceModuleName,
1889
+ sourceScope
1890
+ });
1891
+ };
1868
1892
  var getSafeReplacementNameAndImportFixFactory = ({ context, importedName, imports, referenceNode, sourceModuleName }) => {
1869
1893
  const sourceScope = resolveReferenceScope({
1870
1894
  context,
@@ -2349,7 +2373,18 @@ var orderedRuleNames = [
2349
2373
  "prefer-type-fest-conditional-pick-deep",
2350
2374
  "prefer-type-fest-union-to-tuple",
2351
2375
  "prefer-type-fest-less-than",
2352
- "prefer-type-fest-less-than-or-equal"
2376
+ "prefer-type-fest-less-than-or-equal",
2377
+ "prefer-ts-extras-object-map-values",
2378
+ "prefer-type-fest-conditional-except",
2379
+ "prefer-type-fest-merge",
2380
+ "prefer-type-fest-stringified",
2381
+ "prefer-type-fest-union-to-intersection",
2382
+ "prefer-type-fest-distributed-omit",
2383
+ "prefer-type-fest-distributed-pick",
2384
+ "prefer-type-fest-set-return-type",
2385
+ "prefer-type-fest-asyncify",
2386
+ "prefer-type-fest-pick-index-signature",
2387
+ "prefer-type-fest-conditional-keys"
2353
2388
  ];
2354
2389
  var toRuleCatalogId = (ruleNumber) => `R${String(ruleNumber).padStart(3, "0")}`;
2355
2390
  var isTypefestRuleNamePattern2 = (ruleName) => ruleName.startsWith("prefer-");
@@ -5974,6 +6009,168 @@ var preferTsExtrasObjectKeysRule = createTypedRule({
5974
6009
  });
5975
6010
  var prefer_ts_extras_object_keys_default = preferTsExtrasObjectKeysRule;
5976
6011
 
6012
+ // dist/rules/prefer-ts-extras-object-map-values.js
6013
+ var getSingleExpressionArgument = (callExpression) => {
6014
+ if (callExpression.arguments.length !== 1) {
6015
+ return null;
6016
+ }
6017
+ const [argument] = callExpression.arguments;
6018
+ if (!argument || argument.type === "SpreadElement") {
6019
+ return null;
6020
+ }
6021
+ return argument;
6022
+ };
6023
+ var unwrapTransparentExpression2 = (expression) => {
6024
+ let currentExpression = expression;
6025
+ while (true) {
6026
+ if (currentExpression.type === "TSAsExpression") {
6027
+ currentExpression = currentExpression.expression;
6028
+ continue;
6029
+ }
6030
+ if (currentExpression.type === "TSNonNullExpression") {
6031
+ currentExpression = currentExpression.expression;
6032
+ continue;
6033
+ }
6034
+ if (currentExpression.type === "TSSatisfiesExpression") {
6035
+ currentExpression = currentExpression.expression;
6036
+ continue;
6037
+ }
6038
+ if (currentExpression.type === "TSTypeAssertion") {
6039
+ currentExpression = currentExpression.expression;
6040
+ continue;
6041
+ }
6042
+ return currentExpression;
6043
+ }
6044
+ };
6045
+ var getReturnedExpression = (callback) => {
6046
+ if (callback.body.type !== "BlockStatement") {
6047
+ return callback.body;
6048
+ }
6049
+ if (callback.body.body.length !== 1) {
6050
+ return null;
6051
+ }
6052
+ const [statement] = callback.body.body;
6053
+ if (statement?.type !== "ReturnStatement") {
6054
+ return null;
6055
+ }
6056
+ return statement.argument;
6057
+ };
6058
+ var getKeyIdentifierFromEntriesTupleParameter = (parameter) => {
6059
+ if (parameter.type !== "ArrayPattern" || parameter.elements.length !== 2) {
6060
+ return null;
6061
+ }
6062
+ const [firstElement, secondElement] = parameter.elements;
6063
+ if (firstElement?.type !== "Identifier" || secondElement?.type !== "Identifier") {
6064
+ return null;
6065
+ }
6066
+ return firstElement;
6067
+ };
6068
+ var isKeyPreservingMappedTupleReturn = (returnedExpression, keyIdentifier) => {
6069
+ const unwrappedExpression = unwrapTransparentExpression2(returnedExpression);
6070
+ if (unwrappedExpression.type !== "ArrayExpression" || unwrappedExpression.elements.length !== 2) {
6071
+ return false;
6072
+ }
6073
+ const [firstElement, secondElement] = unwrappedExpression.elements;
6074
+ if (!firstElement || !secondElement || firstElement.type === "SpreadElement" || secondElement.type === "SpreadElement") {
6075
+ return false;
6076
+ }
6077
+ return areEquivalentExpressions(firstElement, keyIdentifier);
6078
+ };
6079
+ var preferTsExtrasObjectMapValuesRule = createTypedRule({
6080
+ create(context) {
6081
+ const tsExtrasImports = collectDirectNamedValueImportsFromSource(context.sourceCode, TS_EXTRAS_MODULE_SOURCE);
6082
+ return {
6083
+ 'CallExpression[callee.type="Identifier"]'(node) {
6084
+ if (node.optional || node.callee.type !== "Identifier") {
6085
+ return;
6086
+ }
6087
+ const objectFromEntriesLocalName = getSafeLocalNameForImportedValue({
6088
+ context,
6089
+ importedName: "objectFromEntries",
6090
+ imports: tsExtrasImports,
6091
+ referenceNode: node,
6092
+ sourceModuleName: TS_EXTRAS_MODULE_SOURCE
6093
+ });
6094
+ if (objectFromEntriesLocalName === null || node.callee.name !== objectFromEntriesLocalName) {
6095
+ return;
6096
+ }
6097
+ const mapCallExpression = getSingleExpressionArgument(node);
6098
+ if (mapCallExpression?.type !== "CallExpression") {
6099
+ return;
6100
+ }
6101
+ const mapMemberCall = getIdentifierPropertyMemberCall({
6102
+ memberName: "map",
6103
+ node: mapCallExpression
6104
+ });
6105
+ if (mapMemberCall === null) {
6106
+ return;
6107
+ }
6108
+ const mapCallback = getSingleExpressionArgument(mapMemberCall);
6109
+ if (mapCallback?.type !== "ArrowFunctionExpression") {
6110
+ return;
6111
+ }
6112
+ const objectEntriesLocalName = getSafeLocalNameForImportedValue({
6113
+ context,
6114
+ importedName: "objectEntries",
6115
+ imports: tsExtrasImports,
6116
+ referenceNode: mapMemberCall,
6117
+ sourceModuleName: TS_EXTRAS_MODULE_SOURCE
6118
+ });
6119
+ if (objectEntriesLocalName === null) {
6120
+ return;
6121
+ }
6122
+ const entriesCallExpression = mapMemberCall.callee.object;
6123
+ if (entriesCallExpression.type !== "CallExpression" || entriesCallExpression.callee.type !== "Identifier" || entriesCallExpression.callee.name !== objectEntriesLocalName || getSingleExpressionArgument(entriesCallExpression) === null) {
6124
+ return;
6125
+ }
6126
+ if (mapCallback.params.length !== 1) {
6127
+ return;
6128
+ }
6129
+ const [tupleParameter] = mapCallback.params;
6130
+ if (tupleParameter === void 0) {
6131
+ return;
6132
+ }
6133
+ const keyIdentifier = getKeyIdentifierFromEntriesTupleParameter(tupleParameter);
6134
+ if (keyIdentifier === null) {
6135
+ return;
6136
+ }
6137
+ const returnedExpression = getReturnedExpression(mapCallback);
6138
+ if (returnedExpression === null) {
6139
+ return;
6140
+ }
6141
+ if (!isKeyPreservingMappedTupleReturn(returnedExpression, keyIdentifier)) {
6142
+ return;
6143
+ }
6144
+ reportWithOptionalFix({
6145
+ context,
6146
+ fix: null,
6147
+ messageId: "preferTsExtrasObjectMapValues",
6148
+ node
6149
+ });
6150
+ }
6151
+ };
6152
+ },
6153
+ defaultOptions: [],
6154
+ meta: {
6155
+ deprecated: false,
6156
+ docs: {
6157
+ description: "require ts-extras objectMapValues over objectFromEntries(objectEntries(...).map(...)) chains that only remap values.",
6158
+ frozen: false,
6159
+ recommended: false,
6160
+ requiresTypeChecking: false,
6161
+ typefestConfigs: ["typefest.configs.experimental"],
6162
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-ts-extras-object-map-values"
6163
+ },
6164
+ messages: {
6165
+ preferTsExtrasObjectMapValues: "Prefer `objectMapValues` from `ts-extras` over `objectFromEntries(objectEntries(...).map(...))` when the map callback preserves keys and only remaps values."
6166
+ },
6167
+ schema: [],
6168
+ type: "suggestion"
6169
+ },
6170
+ name: "prefer-ts-extras-object-map-values"
6171
+ });
6172
+ var prefer_ts_extras_object_map_values_default = preferTsExtrasObjectMapValuesRule;
6173
+
5977
6174
  // dist/rules/prefer-ts-extras-object-values.js
5978
6175
  var preferTsExtrasObjectValuesRule = createTypedRule({
5979
6176
  create(context) {
@@ -6770,6 +6967,10 @@ var prefer_type_fest_array_length_default = preferTypeFestArrayLengthRule;
6770
6967
 
6771
6968
  // dist/_internal/type-reference-node.js
6772
6969
  var isIdentifierTypeReference = (node, identifierName) => node.type === "TSTypeReference" && node.typeName.type === "Identifier" && node.typeName.name === identifierName;
6970
+ var unwrapParenthesizedTypeNode = (node) => {
6971
+ const parenthesizedCandidate = node;
6972
+ return parenthesizedCandidate.type === "TSParenthesizedType" && parenthesizedCandidate.typeAnnotation !== void 0 ? unwrapParenthesizedTypeNode(parenthesizedCandidate.typeAnnotation) : node;
6973
+ };
6773
6974
 
6774
6975
  // dist/rules/prefer-type-fest-arrayable.js
6775
6976
  var ARRAY_TYPE_NAME = "Array";
@@ -6925,34 +7126,98 @@ var preferTypeFestAsyncReturnTypeRule = createTypedRule({
6925
7126
  });
6926
7127
  var prefer_type_fest_async_return_type_default = preferTypeFestAsyncReturnTypeRule;
6927
7128
 
6928
- // dist/rules/prefer-type-fest-conditional-pick-deep.js
6929
- var conditionalPickDeepAliasReplacements = {
6930
- PickDeepByType: "ConditionalPickDeep",
6931
- PickDeepByTypes: "ConditionalPickDeep"
7129
+ // dist/_internal/function-type-reference-patterns.js
7130
+ var getSingleTypeArgument2 = (node) => {
7131
+ const typeArguments = node.typeArguments?.params ?? [];
7132
+ if (typeArguments.length !== 1) {
7133
+ return null;
7134
+ }
7135
+ const [onlyTypeArgument] = typeArguments;
7136
+ return onlyTypeArgument ?? null;
6932
7137
  };
6933
- var preferTypeFestConditionalPickDeepRule = createTypedRule({
7138
+ var getParameterTypeAnnotation = (parameter) => {
7139
+ if (parameter.type === "Identifier") {
7140
+ return parameter.typeAnnotation === void 0 ? null : unwrapParenthesizedTypeNode(parameter.typeAnnotation.typeAnnotation);
7141
+ }
7142
+ if (parameter.type !== "RestElement") {
7143
+ return null;
7144
+ }
7145
+ return parameter.typeAnnotation === void 0 ? null : unwrapParenthesizedTypeNode(parameter.typeAnnotation.typeAnnotation);
7146
+ };
7147
+ var getParametersFunctionArgumentFromFunctionType = (node) => {
7148
+ if (node.params.length !== 1) {
7149
+ return null;
7150
+ }
7151
+ const [onlyParameter] = node.params;
7152
+ if (onlyParameter?.type !== "RestElement") {
7153
+ return null;
7154
+ }
7155
+ const restParameterType = getParameterTypeAnnotation(onlyParameter);
7156
+ if (restParameterType?.type !== "TSTypeReference" || !isIdentifierTypeReference(restParameterType, "Parameters")) {
7157
+ return null;
7158
+ }
7159
+ return getSingleTypeArgument2(restParameterType);
7160
+ };
7161
+ var isReturnTypeReferenceForFunction = (node, functionType) => {
7162
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7163
+ if (normalizedNode.type !== "TSTypeReference" || !isIdentifierTypeReference(normalizedNode, "ReturnType")) {
7164
+ return false;
7165
+ }
7166
+ const referencedFunctionType = getSingleTypeArgument2(normalizedNode);
7167
+ return referencedFunctionType !== null && areEquivalentTypeNodes(unwrapParenthesizedTypeNode(referencedFunctionType), unwrapParenthesizedTypeNode(functionType));
7168
+ };
7169
+ var isPromiseAwaitedReturnTypeReferenceForFunction = (node, functionType) => {
7170
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7171
+ if (normalizedNode.type !== "TSTypeReference" || !isIdentifierTypeReference(normalizedNode, "Promise")) {
7172
+ return false;
7173
+ }
7174
+ const promisedType = getSingleTypeArgument2(normalizedNode);
7175
+ if (promisedType?.type !== "TSTypeReference" || !isIdentifierTypeReference(promisedType, "Awaited")) {
7176
+ return false;
7177
+ }
7178
+ const awaitedInnerType = getSingleTypeArgument2(promisedType);
7179
+ return awaitedInnerType !== null && isReturnTypeReferenceForFunction(awaitedInnerType, functionType);
7180
+ };
7181
+
7182
+ // dist/rules/prefer-type-fest-asyncify.js
7183
+ var isAsyncifyEquivalentSetReturnTypeReference = (node, setReturnTypeLocalNames) => {
7184
+ if (node.typeName.type !== "Identifier" || !setContainsValue(setReturnTypeLocalNames, node.typeName.name)) {
7185
+ return false;
7186
+ }
7187
+ const typeArguments = node.typeArguments?.params;
7188
+ if (typeArguments?.length !== 2) {
7189
+ return false;
7190
+ }
7191
+ const [functionType, returnType] = typeArguments;
7192
+ return functionType !== void 0 && returnType !== void 0 && isPromiseAwaitedReturnTypeReferenceForFunction(returnType, functionType);
7193
+ };
7194
+ var preferTypeFestAsyncifyRule = createTypedRule({
6934
7195
  create(context) {
6935
- const importedAliasMatches = collectImportedTypeAliasMatches(context.sourceCode, conditionalPickDeepAliasReplacements);
6936
- const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7196
+ const setReturnTypeLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, "SetReturnType");
6937
7197
  return {
6938
- 'TSTypeReference[typeName.type="Identifier"]'(node) {
6939
- if (node.typeName.type !== "Identifier") {
7198
+ TSFunctionType(node) {
7199
+ const functionType = getParametersFunctionArgumentFromFunctionType(node);
7200
+ const returnType = node.returnType?.typeAnnotation;
7201
+ if (functionType === null || returnType === void 0 || !isPromiseAwaitedReturnTypeReferenceForFunction(returnType, functionType)) {
6940
7202
  return;
6941
7203
  }
6942
- const importedAliasMatch = importedAliasMatches.get(node.typeName.name);
6943
- if (!importedAliasMatch) {
7204
+ reportWithOptionalFix({
7205
+ context,
7206
+ fix: null,
7207
+ messageId: "preferAsyncify",
7208
+ node
7209
+ });
7210
+ },
7211
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
7212
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7213
+ if (normalizedNode.type !== "TSTypeReference" || !isAsyncifyEquivalentSetReturnTypeReference(normalizedNode, setReturnTypeLocalNames)) {
6944
7214
  return;
6945
7215
  }
6946
- const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, importedAliasMatch.replacementName, typeFestDirectImports);
6947
7216
  reportWithOptionalFix({
6948
7217
  context,
6949
- data: {
6950
- alias: importedAliasMatch.importedName,
6951
- replacement: importedAliasMatch.replacementName
6952
- },
6953
- fix: aliasReplacementFix,
6954
- messageId: "preferConditionalPickDeep",
6955
- node
7218
+ fix: null,
7219
+ messageId: "preferAsyncify",
7220
+ node: normalizedNode
6956
7221
  });
6957
7222
  }
6958
7223
  };
@@ -6961,55 +7226,67 @@ var preferTypeFestConditionalPickDeepRule = createTypedRule({
6961
7226
  meta: {
6962
7227
  deprecated: false,
6963
7228
  docs: {
6964
- description: "require TypeFest ConditionalPickDeep over imported aliases such as PickDeepByTypes.",
7229
+ description: "require TypeFest Asyncify over async function-type wrappers built from Parameters + Promise<Awaited<ReturnType<...>>>.",
6965
7230
  frozen: false,
6966
- recommended: true,
7231
+ recommended: false,
6967
7232
  requiresTypeChecking: false,
6968
- typefestConfigs: [
6969
- "typefest.configs.recommended",
6970
- "typefest.configs.strict",
6971
- "typefest.configs.all",
6972
- "typefest.configs.type-fest/types"
6973
- ],
6974
- url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-pick-deep"
7233
+ typefestConfigs: ["typefest.configs.experimental"],
7234
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-asyncify"
6975
7235
  },
6976
- fixable: "code",
6977
7236
  messages: {
6978
- preferConditionalPickDeep: "Prefer `{{replacement}}` from type-fest for deep conditional property filtering instead of legacy alias `{{alias}}`."
7237
+ preferAsyncify: "Prefer `Asyncify<Function>` from type-fest over manual async wrappers built from `Parameters<Function>` and `Promise<Awaited<ReturnType<Function>>>`."
6979
7238
  },
6980
7239
  schema: [],
6981
7240
  type: "suggestion"
6982
7241
  },
6983
- name: "prefer-type-fest-conditional-pick-deep"
7242
+ name: "prefer-type-fest-asyncify"
6984
7243
  });
6985
- var prefer_type_fest_conditional_pick_deep_default = preferTypeFestConditionalPickDeepRule;
7244
+ var prefer_type_fest_asyncify_default = preferTypeFestAsyncifyRule;
6986
7245
 
6987
- // dist/rules/prefer-type-fest-conditional-pick.js
6988
- var conditionalPickAliasReplacements = {
6989
- PickByTypes: "ConditionalPick"
7246
+ // dist/rules/prefer-type-fest-conditional-except.js
7247
+ var getConditionalKeysReference = (node, conditionalKeysLocalNames) => {
7248
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7249
+ if (normalizedNode.type !== "TSTypeReference" || normalizedNode.typeName.type !== "Identifier" || !setContainsValue(conditionalKeysLocalNames, normalizedNode.typeName.name)) {
7250
+ return null;
7251
+ }
7252
+ return normalizedNode;
6990
7253
  };
6991
- var preferTypeFestConditionalPickRule = createTypedRule({
7254
+ var preferTypeFestConditionalExceptRule = createTypedRule({
6992
7255
  create(context) {
6993
- const importedAliasMatches = collectImportedTypeAliasMatches(context.sourceCode, conditionalPickAliasReplacements);
6994
- const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7256
+ const exceptLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, "Except");
7257
+ const conditionalKeysLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, "ConditionalKeys");
6995
7258
  return {
6996
7259
  'TSTypeReference[typeName.type="Identifier"]'(node) {
6997
- if (node.typeName.type !== "Identifier") {
7260
+ if (node.typeName.type !== "Identifier" || !setContainsValue(exceptLocalNames, node.typeName.name)) {
6998
7261
  return;
6999
7262
  }
7000
- const importedAliasMatch = importedAliasMatches.get(node.typeName.name);
7001
- if (!importedAliasMatch) {
7263
+ const typeArguments = node.typeArguments?.params;
7264
+ if (typeArguments?.length !== 2) {
7265
+ return;
7266
+ }
7267
+ const [baseType, excludedKeysType] = typeArguments;
7268
+ if (baseType === void 0 || excludedKeysType === void 0) {
7269
+ return;
7270
+ }
7271
+ const conditionalKeysReference = getConditionalKeysReference(excludedKeysType, conditionalKeysLocalNames);
7272
+ if (conditionalKeysReference === null) {
7273
+ return;
7274
+ }
7275
+ const conditionalKeysArguments = conditionalKeysReference.typeArguments?.params;
7276
+ if (conditionalKeysArguments?.length !== 2) {
7277
+ return;
7278
+ }
7279
+ const [conditionalBaseType] = conditionalKeysArguments;
7280
+ if (conditionalBaseType === void 0) {
7281
+ return;
7282
+ }
7283
+ if (!areEquivalentTypeNodes(baseType, conditionalBaseType)) {
7002
7284
  return;
7003
7285
  }
7004
- const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, importedAliasMatch.replacementName, typeFestDirectImports);
7005
7286
  reportWithOptionalFix({
7006
7287
  context,
7007
- data: {
7008
- alias: importedAliasMatch.importedName,
7009
- replacement: importedAliasMatch.replacementName
7010
- },
7011
- fix: aliasReplacementFix,
7012
- messageId: "preferConditionalPick",
7288
+ fix: null,
7289
+ messageId: "preferConditionalExcept",
7013
7290
  node
7014
7291
  });
7015
7292
  }
@@ -7019,42 +7296,215 @@ var preferTypeFestConditionalPickRule = createTypedRule({
7019
7296
  meta: {
7020
7297
  deprecated: false,
7021
7298
  docs: {
7022
- description: "require TypeFest ConditionalPick over imported aliases such as PickByTypes.",
7299
+ description: "require TypeFest ConditionalExcept over Except<T, ConditionalKeys<T, Condition>> compositions.",
7023
7300
  frozen: false,
7024
- recommended: true,
7301
+ recommended: false,
7025
7302
  requiresTypeChecking: false,
7026
- typefestConfigs: [
7027
- "typefest.configs.recommended",
7028
- "typefest.configs.strict",
7029
- "typefest.configs.all",
7030
- "typefest.configs.type-fest/types"
7031
- ],
7032
- url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-pick"
7303
+ typefestConfigs: ["typefest.configs.experimental"],
7304
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-except"
7033
7305
  },
7034
- fixable: "code",
7035
7306
  messages: {
7036
- preferConditionalPick: "Prefer `{{replacement}}` from type-fest to pick keys whose values match a condition instead of legacy alias `{{alias}}`."
7307
+ preferConditionalExcept: "Prefer `ConditionalExcept<Base, Condition>` from type-fest over `Except<Base, ConditionalKeys<Base, Condition>>` when excluding keys by value condition."
7037
7308
  },
7038
7309
  schema: [],
7039
7310
  type: "suggestion"
7040
7311
  },
7041
- name: "prefer-type-fest-conditional-pick"
7312
+ name: "prefer-type-fest-conditional-except"
7042
7313
  });
7043
- var prefer_type_fest_conditional_pick_default = preferTypeFestConditionalPickRule;
7314
+ var prefer_type_fest_conditional_except_default = preferTypeFestConditionalExceptRule;
7044
7315
 
7045
- // dist/rules/prefer-type-fest-constructor.js
7046
- var import_ts_extras33 = require("ts-extras");
7047
- var preferTypeFestConstructorRule = createTypedRule({
7048
- create(context) {
7049
- const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7050
- const { sourceCode } = context;
7051
- return {
7052
- TSConstructorType(node) {
7053
- if (node.abstract) {
7054
- return;
7055
- }
7056
- const replacementFix = !(0, import_ts_extras33.isDefined)(node.typeParameters) && (0, import_ts_extras33.isDefined)(node.returnType) ? createSafeTypeNodeTextReplacementFix(node, "Constructor", `Constructor<${sourceCode.getText(node.returnType.typeAnnotation)}, [${(0, import_ts_extras33.arrayJoin)(node.params.map((parameter) => sourceCode.getText(parameter)), ", ")}]>`, typeFestDirectImports) : null;
7057
- reportWithOptionalFix({
7316
+ // dist/rules/prefer-type-fest-conditional-keys.js
7317
+ var hasConditionalKeysKeyRemapShape = (node) => {
7318
+ if (node.operator !== "keyof" || node.typeAnnotation === void 0) {
7319
+ return false;
7320
+ }
7321
+ const normalizedOperand = unwrapParenthesizedTypeNode(node.typeAnnotation);
7322
+ if (normalizedOperand.type !== "TSMappedType" || normalizedOperand.key.type !== "Identifier") {
7323
+ return false;
7324
+ }
7325
+ const mappedKeyName = normalizedOperand.key.name;
7326
+ const constraint = normalizedOperand.constraint;
7327
+ if (constraint?.type !== "TSTypeOperator" || constraint.operator !== "keyof" || constraint.typeAnnotation === void 0) {
7328
+ return false;
7329
+ }
7330
+ const baseType = unwrapParenthesizedTypeNode(constraint.typeAnnotation);
7331
+ const keyRemapType = normalizedOperand.nameType;
7332
+ if (keyRemapType?.type !== "TSConditionalType") {
7333
+ return false;
7334
+ }
7335
+ const checkedValueType = unwrapParenthesizedTypeNode(keyRemapType.checkType);
7336
+ if (checkedValueType.type !== "TSIndexedAccessType" || !areEquivalentTypeNodes(unwrapParenthesizedTypeNode(checkedValueType.objectType), baseType) || checkedValueType.indexType.type !== "TSTypeReference" || checkedValueType.indexType.typeName.type !== "Identifier" || checkedValueType.indexType.typeName.name !== mappedKeyName) {
7337
+ return false;
7338
+ }
7339
+ return keyRemapType.trueType.type === "TSTypeReference" && keyRemapType.trueType.typeName.type === "Identifier" && keyRemapType.trueType.typeName.name === mappedKeyName && keyRemapType.falseType.type === "TSNeverKeyword";
7340
+ };
7341
+ var preferTypeFestConditionalKeysRule = createTypedRule({
7342
+ create(context) {
7343
+ return {
7344
+ TSTypeOperator(node) {
7345
+ if (!hasConditionalKeysKeyRemapShape(node)) {
7346
+ return;
7347
+ }
7348
+ reportWithOptionalFix({
7349
+ context,
7350
+ fix: null,
7351
+ messageId: "preferConditionalKeys",
7352
+ node
7353
+ });
7354
+ }
7355
+ };
7356
+ },
7357
+ defaultOptions: [],
7358
+ meta: {
7359
+ deprecated: false,
7360
+ docs: {
7361
+ description: "require TypeFest ConditionalKeys over keyof-remapped mapped types that filter keys by value condition.",
7362
+ frozen: false,
7363
+ recommended: false,
7364
+ requiresTypeChecking: false,
7365
+ typefestConfigs: ["typefest.configs.experimental"],
7366
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-keys"
7367
+ },
7368
+ messages: {
7369
+ preferConditionalKeys: "Prefer `ConditionalKeys<Base, Condition>` from type-fest over manual `keyof { [K in keyof Base as Base[K] extends Condition ? K : never]: ... }` key filters."
7370
+ },
7371
+ schema: [],
7372
+ type: "suggestion"
7373
+ },
7374
+ name: "prefer-type-fest-conditional-keys"
7375
+ });
7376
+ var prefer_type_fest_conditional_keys_default = preferTypeFestConditionalKeysRule;
7377
+
7378
+ // dist/rules/prefer-type-fest-conditional-pick-deep.js
7379
+ var conditionalPickDeepAliasReplacements = {
7380
+ PickDeepByType: "ConditionalPickDeep",
7381
+ PickDeepByTypes: "ConditionalPickDeep"
7382
+ };
7383
+ var preferTypeFestConditionalPickDeepRule = createTypedRule({
7384
+ create(context) {
7385
+ const importedAliasMatches = collectImportedTypeAliasMatches(context.sourceCode, conditionalPickDeepAliasReplacements);
7386
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7387
+ return {
7388
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
7389
+ if (node.typeName.type !== "Identifier") {
7390
+ return;
7391
+ }
7392
+ const importedAliasMatch = importedAliasMatches.get(node.typeName.name);
7393
+ if (!importedAliasMatch) {
7394
+ return;
7395
+ }
7396
+ const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, importedAliasMatch.replacementName, typeFestDirectImports);
7397
+ reportWithOptionalFix({
7398
+ context,
7399
+ data: {
7400
+ alias: importedAliasMatch.importedName,
7401
+ replacement: importedAliasMatch.replacementName
7402
+ },
7403
+ fix: aliasReplacementFix,
7404
+ messageId: "preferConditionalPickDeep",
7405
+ node
7406
+ });
7407
+ }
7408
+ };
7409
+ },
7410
+ defaultOptions: [],
7411
+ meta: {
7412
+ deprecated: false,
7413
+ docs: {
7414
+ description: "require TypeFest ConditionalPickDeep over imported aliases such as PickDeepByTypes.",
7415
+ frozen: false,
7416
+ recommended: true,
7417
+ requiresTypeChecking: false,
7418
+ typefestConfigs: [
7419
+ "typefest.configs.recommended",
7420
+ "typefest.configs.strict",
7421
+ "typefest.configs.all",
7422
+ "typefest.configs.type-fest/types"
7423
+ ],
7424
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-pick-deep"
7425
+ },
7426
+ fixable: "code",
7427
+ messages: {
7428
+ preferConditionalPickDeep: "Prefer `{{replacement}}` from type-fest for deep conditional property filtering instead of legacy alias `{{alias}}`."
7429
+ },
7430
+ schema: [],
7431
+ type: "suggestion"
7432
+ },
7433
+ name: "prefer-type-fest-conditional-pick-deep"
7434
+ });
7435
+ var prefer_type_fest_conditional_pick_deep_default = preferTypeFestConditionalPickDeepRule;
7436
+
7437
+ // dist/rules/prefer-type-fest-conditional-pick.js
7438
+ var conditionalPickAliasReplacements = {
7439
+ PickByTypes: "ConditionalPick"
7440
+ };
7441
+ var preferTypeFestConditionalPickRule = createTypedRule({
7442
+ create(context) {
7443
+ const importedAliasMatches = collectImportedTypeAliasMatches(context.sourceCode, conditionalPickAliasReplacements);
7444
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7445
+ return {
7446
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
7447
+ if (node.typeName.type !== "Identifier") {
7448
+ return;
7449
+ }
7450
+ const importedAliasMatch = importedAliasMatches.get(node.typeName.name);
7451
+ if (!importedAliasMatch) {
7452
+ return;
7453
+ }
7454
+ const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, importedAliasMatch.replacementName, typeFestDirectImports);
7455
+ reportWithOptionalFix({
7456
+ context,
7457
+ data: {
7458
+ alias: importedAliasMatch.importedName,
7459
+ replacement: importedAliasMatch.replacementName
7460
+ },
7461
+ fix: aliasReplacementFix,
7462
+ messageId: "preferConditionalPick",
7463
+ node
7464
+ });
7465
+ }
7466
+ };
7467
+ },
7468
+ defaultOptions: [],
7469
+ meta: {
7470
+ deprecated: false,
7471
+ docs: {
7472
+ description: "require TypeFest ConditionalPick over imported aliases such as PickByTypes.",
7473
+ frozen: false,
7474
+ recommended: true,
7475
+ requiresTypeChecking: false,
7476
+ typefestConfigs: [
7477
+ "typefest.configs.recommended",
7478
+ "typefest.configs.strict",
7479
+ "typefest.configs.all",
7480
+ "typefest.configs.type-fest/types"
7481
+ ],
7482
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-conditional-pick"
7483
+ },
7484
+ fixable: "code",
7485
+ messages: {
7486
+ preferConditionalPick: "Prefer `{{replacement}}` from type-fest to pick keys whose values match a condition instead of legacy alias `{{alias}}`."
7487
+ },
7488
+ schema: [],
7489
+ type: "suggestion"
7490
+ },
7491
+ name: "prefer-type-fest-conditional-pick"
7492
+ });
7493
+ var prefer_type_fest_conditional_pick_default = preferTypeFestConditionalPickRule;
7494
+
7495
+ // dist/rules/prefer-type-fest-constructor.js
7496
+ var import_ts_extras33 = require("ts-extras");
7497
+ var preferTypeFestConstructorRule = createTypedRule({
7498
+ create(context) {
7499
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
7500
+ const { sourceCode } = context;
7501
+ return {
7502
+ TSConstructorType(node) {
7503
+ if (node.abstract) {
7504
+ return;
7505
+ }
7506
+ const replacementFix = !(0, import_ts_extras33.isDefined)(node.typeParameters) && (0, import_ts_extras33.isDefined)(node.returnType) ? createSafeTypeNodeTextReplacementFix(node, "Constructor", `Constructor<${sourceCode.getText(node.returnType.typeAnnotation)}, [${(0, import_ts_extras33.arrayJoin)(node.params.map((parameter) => sourceCode.getText(parameter)), ", ")}]>`, typeFestDirectImports) : null;
7507
+ reportWithOptionalFix({
7058
7508
  context,
7059
7509
  fix: replacementFix,
7060
7510
  messageId: "preferConstructorSignature",
@@ -7090,6 +7540,145 @@ var preferTypeFestConstructorRule = createTypedRule({
7090
7540
  });
7091
7541
  var prefer_type_fest_constructor_default = preferTypeFestConstructorRule;
7092
7542
 
7543
+ // dist/rules/prefer-type-fest-distributed-omit.js
7544
+ var isDistributiveConditionalExtendsType = (node) => {
7545
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7546
+ return normalizedNode.type === "TSAnyKeyword" || normalizedNode.type === "TSUnknownKeyword";
7547
+ };
7548
+ var isDistributedOmitEquivalent = (node) => {
7549
+ if (node.falseType.type !== "TSNeverKeyword" || !isDistributiveConditionalExtendsType(node.extendsType)) {
7550
+ return false;
7551
+ }
7552
+ const normalizedTrueType = unwrapParenthesizedTypeNode(node.trueType);
7553
+ if (normalizedTrueType.type !== "TSTypeReference" || !isIdentifierTypeReference(normalizedTrueType, "Omit")) {
7554
+ return false;
7555
+ }
7556
+ const typeArguments = normalizedTrueType.typeArguments?.params;
7557
+ if (typeArguments?.length !== 2) {
7558
+ return false;
7559
+ }
7560
+ const [objectType] = typeArguments;
7561
+ return objectType !== void 0 && areEquivalentTypeNodes(unwrapParenthesizedTypeNode(objectType), unwrapParenthesizedTypeNode(node.checkType));
7562
+ };
7563
+ var preferTypeFestDistributedOmitRule = createTypedRule({
7564
+ create(context) {
7565
+ return {
7566
+ TSConditionalType(node) {
7567
+ if (!isDistributedOmitEquivalent(node)) {
7568
+ return;
7569
+ }
7570
+ reportWithOptionalFix({
7571
+ context,
7572
+ fix: null,
7573
+ messageId: "preferDistributedOmit",
7574
+ node
7575
+ });
7576
+ }
7577
+ };
7578
+ },
7579
+ defaultOptions: [],
7580
+ meta: {
7581
+ deprecated: false,
7582
+ docs: {
7583
+ description: "require TypeFest DistributedOmit over distributive conditional helpers of the form T extends unknown ? Omit<T, K> : never.",
7584
+ frozen: false,
7585
+ recommended: false,
7586
+ requiresTypeChecking: false,
7587
+ typefestConfigs: ["typefest.configs.experimental"],
7588
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-distributed-omit"
7589
+ },
7590
+ messages: {
7591
+ preferDistributedOmit: "Prefer `DistributedOmit<ObjectType, KeyType>` from type-fest over distributive conditional helpers like `T extends unknown ? Omit<T, K> : never`."
7592
+ },
7593
+ schema: [],
7594
+ type: "suggestion"
7595
+ },
7596
+ name: "prefer-type-fest-distributed-omit"
7597
+ });
7598
+ var prefer_type_fest_distributed_omit_default = preferTypeFestDistributedOmitRule;
7599
+
7600
+ // dist/rules/prefer-type-fest-distributed-pick.js
7601
+ var isDistributiveConditionalExtendsType2 = (node) => {
7602
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7603
+ return normalizedNode.type === "TSAnyKeyword" || normalizedNode.type === "TSUnknownKeyword";
7604
+ };
7605
+ var isKeyofBaseType = (node, baseType) => {
7606
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7607
+ if (normalizedNode.type !== "TSTypeOperator" || normalizedNode.operator !== "keyof" || normalizedNode.typeAnnotation === void 0) {
7608
+ return false;
7609
+ }
7610
+ return areEquivalentTypeNodes(unwrapParenthesizedTypeNode(normalizedNode.typeAnnotation), unwrapParenthesizedTypeNode(baseType));
7611
+ };
7612
+ var isExtractOverKeyofBaseType = (node, baseType) => {
7613
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
7614
+ if (normalizedNode.type !== "TSTypeReference" || !isIdentifierTypeReference(normalizedNode, "Extract")) {
7615
+ return false;
7616
+ }
7617
+ const typeArguments = normalizedNode.typeArguments?.params;
7618
+ if (typeArguments?.length !== 2) {
7619
+ return false;
7620
+ }
7621
+ const [, extractedFromType] = typeArguments;
7622
+ return extractedFromType !== void 0 && isKeyofBaseType(extractedFromType, baseType);
7623
+ };
7624
+ var isDistributedPickEquivalent = (node) => {
7625
+ if (node.falseType.type !== "TSNeverKeyword" || !isDistributiveConditionalExtendsType2(node.extendsType)) {
7626
+ return false;
7627
+ }
7628
+ const normalizedTrueType = unwrapParenthesizedTypeNode(node.trueType);
7629
+ if (normalizedTrueType.type !== "TSTypeReference" || !isIdentifierTypeReference(normalizedTrueType, "Pick")) {
7630
+ return false;
7631
+ }
7632
+ const typeArguments = normalizedTrueType.typeArguments?.params;
7633
+ if (typeArguments?.length !== 2) {
7634
+ return false;
7635
+ }
7636
+ const [objectType, selectedKeysType] = typeArguments;
7637
+ if (objectType === void 0 || selectedKeysType === void 0) {
7638
+ return false;
7639
+ }
7640
+ if (!areEquivalentTypeNodes(unwrapParenthesizedTypeNode(objectType), unwrapParenthesizedTypeNode(node.checkType))) {
7641
+ return false;
7642
+ }
7643
+ return !isIdentifierTypeReference(unwrapParenthesizedTypeNode(selectedKeysType), "Extract") || isExtractOverKeyofBaseType(selectedKeysType, node.checkType);
7644
+ };
7645
+ var preferTypeFestDistributedPickRule = createTypedRule({
7646
+ create(context) {
7647
+ return {
7648
+ TSConditionalType(node) {
7649
+ if (!isDistributedPickEquivalent(node)) {
7650
+ return;
7651
+ }
7652
+ reportWithOptionalFix({
7653
+ context,
7654
+ fix: null,
7655
+ messageId: "preferDistributedPick",
7656
+ node
7657
+ });
7658
+ }
7659
+ };
7660
+ },
7661
+ defaultOptions: [],
7662
+ meta: {
7663
+ deprecated: false,
7664
+ docs: {
7665
+ description: "require TypeFest DistributedPick over distributive conditional helpers of the form T extends unknown ? Pick<T, K> : never.",
7666
+ frozen: false,
7667
+ recommended: false,
7668
+ requiresTypeChecking: false,
7669
+ typefestConfigs: ["typefest.configs.experimental"],
7670
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-distributed-pick"
7671
+ },
7672
+ messages: {
7673
+ preferDistributedPick: "Prefer `DistributedPick<ObjectType, KeyType>` from type-fest over distributive conditional helpers like `T extends unknown ? Pick<T, K> : never`."
7674
+ },
7675
+ schema: [],
7676
+ type: "suggestion"
7677
+ },
7678
+ name: "prefer-type-fest-distributed-pick"
7679
+ });
7680
+ var prefer_type_fest_distributed_pick_default = preferTypeFestDistributedPickRule;
7681
+
7093
7682
  // dist/rules/prefer-type-fest-except.js
7094
7683
  var OMIT_TYPE_NAME = "Omit";
7095
7684
  var exceptAliasReplacements = {
@@ -8073,6 +8662,76 @@ var preferTypeFestMergeExclusiveRule = createTypedRule({
8073
8662
  });
8074
8663
  var prefer_type_fest_merge_exclusive_default = preferTypeFestMergeExclusiveRule;
8075
8664
 
8665
+ // dist/rules/prefer-type-fest-merge.js
8666
+ var isMergeIntersectionExceptReference = (node, siblingType, exceptLocalNames) => {
8667
+ if (node.typeName.type !== "Identifier" || !setContainsValue(exceptLocalNames, node.typeName.name)) {
8668
+ return false;
8669
+ }
8670
+ const typeArguments = node.typeArguments?.params;
8671
+ if (typeArguments?.length !== 2) {
8672
+ return false;
8673
+ }
8674
+ const [, omittedKeysType] = typeArguments;
8675
+ if (omittedKeysType === void 0) {
8676
+ return false;
8677
+ }
8678
+ const normalizedOmittedKeysType = unwrapParenthesizedTypeNode(omittedKeysType);
8679
+ if (normalizedOmittedKeysType.type !== "TSTypeOperator" || normalizedOmittedKeysType.operator !== "keyof") {
8680
+ return false;
8681
+ }
8682
+ const keyedSourceType = normalizedOmittedKeysType.typeAnnotation;
8683
+ if (keyedSourceType === void 0) {
8684
+ return false;
8685
+ }
8686
+ return areEquivalentTypeNodes(unwrapParenthesizedTypeNode(siblingType), keyedSourceType);
8687
+ };
8688
+ var preferTypeFestMergeRule = createTypedRule({
8689
+ create(context) {
8690
+ const exceptLocalNames = collectNamedImportLocalNamesFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE, "Except");
8691
+ return {
8692
+ 'TSIntersectionType > TSTypeReference[typeName.type="Identifier"]'(node) {
8693
+ const intersectionNode = node.parent;
8694
+ if (intersectionNode?.type !== "TSIntersectionType" || intersectionNode.types.length !== 2) {
8695
+ return;
8696
+ }
8697
+ const [leftType, rightType] = intersectionNode.types;
8698
+ if (leftType === void 0 || rightType === void 0) {
8699
+ return;
8700
+ }
8701
+ const siblingType = leftType === node ? rightType : leftType;
8702
+ if (!isMergeIntersectionExceptReference(node, siblingType, exceptLocalNames)) {
8703
+ return;
8704
+ }
8705
+ reportWithOptionalFix({
8706
+ context,
8707
+ fix: null,
8708
+ messageId: "preferMerge",
8709
+ node: intersectionNode
8710
+ });
8711
+ }
8712
+ };
8713
+ },
8714
+ defaultOptions: [],
8715
+ meta: {
8716
+ deprecated: false,
8717
+ docs: {
8718
+ description: "require TypeFest Merge over Except<Destination, keyof Source> & Source intersections.",
8719
+ frozen: false,
8720
+ recommended: false,
8721
+ requiresTypeChecking: false,
8722
+ typefestConfigs: ["typefest.configs.experimental"],
8723
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-merge"
8724
+ },
8725
+ messages: {
8726
+ preferMerge: "Prefer `Merge<Destination, Source>` from type-fest over `Except<Destination, keyof Source> & Source` when the second object cleanly overrides the first."
8727
+ },
8728
+ schema: [],
8729
+ type: "suggestion"
8730
+ },
8731
+ name: "prefer-type-fest-merge"
8732
+ });
8733
+ var prefer_type_fest_merge_default = preferTypeFestMergeRule;
8734
+
8076
8735
  // dist/rules/prefer-type-fest-non-empty-tuple.js
8077
8736
  var getRequiredTupleElementType = (element) => {
8078
8737
  if (element.type === "TSNamedTupleMember") {
@@ -8460,6 +9119,83 @@ var preferTypeFestPartialDeepRule = createTypedRule({
8460
9119
  });
8461
9120
  var prefer_type_fest_partial_deep_default = preferTypeFestPartialDeepRule;
8462
9121
 
9122
+ // dist/rules/prefer-type-fest-pick-index-signature.js
9123
+ var import_ts_extras37 = require("ts-extras");
9124
+ var isEmptyObjectTypeLiteral = (node) => node.type === "TSTypeLiteral" && node.members.length === 0;
9125
+ var hasPickIndexSignatureMappedTypeShape = (node) => {
9126
+ if (node.key.type !== "Identifier") {
9127
+ return false;
9128
+ }
9129
+ if (node.readonly !== false && (0, import_ts_extras37.isDefined)(node.readonly)) {
9130
+ return false;
9131
+ }
9132
+ if (node.optional !== false && (0, import_ts_extras37.isDefined)(node.optional)) {
9133
+ return false;
9134
+ }
9135
+ const constraint = node.constraint;
9136
+ if (constraint?.type !== "TSTypeOperator" || constraint.operator !== "keyof" || constraint.typeAnnotation === void 0) {
9137
+ return false;
9138
+ }
9139
+ const baseType = unwrapParenthesizedTypeNode(constraint.typeAnnotation);
9140
+ const indexedValueType = node.typeAnnotation;
9141
+ if (indexedValueType?.type !== "TSIndexedAccessType" || !areEquivalentTypeNodes(unwrapParenthesizedTypeNode(indexedValueType.objectType), baseType) || indexedValueType.indexType.type !== "TSTypeReference" || indexedValueType.indexType.typeName.type !== "Identifier" || indexedValueType.indexType.typeName.name !== node.key.name) {
9142
+ return false;
9143
+ }
9144
+ const keyRemapType = node.nameType;
9145
+ if (keyRemapType?.type !== "TSConditionalType") {
9146
+ return false;
9147
+ }
9148
+ if (!isEmptyObjectTypeLiteral(unwrapParenthesizedTypeNode(keyRemapType.checkType)) || keyRemapType.falseType.type !== "TSNeverKeyword" || keyRemapType.trueType.type !== "TSTypeReference" || keyRemapType.trueType.typeName.type !== "Identifier" || keyRemapType.trueType.typeName.name !== node.key.name) {
9149
+ return false;
9150
+ }
9151
+ const normalizedExtendsType = unwrapParenthesizedTypeNode(keyRemapType.extendsType);
9152
+ if (normalizedExtendsType.type !== "TSTypeReference" || !isIdentifierTypeReference(normalizedExtendsType, "Record")) {
9153
+ return false;
9154
+ }
9155
+ const recordTypeArguments = normalizedExtendsType.typeArguments?.params;
9156
+ if (recordTypeArguments?.length !== 2) {
9157
+ return false;
9158
+ }
9159
+ const [recordKeyType, recordValueType] = recordTypeArguments;
9160
+ return recordKeyType !== void 0 && recordValueType?.type === "TSUnknownKeyword" && recordKeyType.type === "TSTypeReference" && recordKeyType.typeName.type === "Identifier" && recordKeyType.typeName.name === node.key.name;
9161
+ };
9162
+ var preferTypeFestPickIndexSignatureRule = createTypedRule({
9163
+ create(context) {
9164
+ return {
9165
+ TSMappedType(node) {
9166
+ if (!hasPickIndexSignatureMappedTypeShape(node)) {
9167
+ return;
9168
+ }
9169
+ reportWithOptionalFix({
9170
+ context,
9171
+ fix: null,
9172
+ messageId: "preferPickIndexSignature",
9173
+ node
9174
+ });
9175
+ }
9176
+ };
9177
+ },
9178
+ defaultOptions: [],
9179
+ meta: {
9180
+ deprecated: false,
9181
+ docs: {
9182
+ description: "require TypeFest PickIndexSignature over manual mapped types that keep only index signatures.",
9183
+ frozen: false,
9184
+ recommended: false,
9185
+ requiresTypeChecking: false,
9186
+ typefestConfigs: ["typefest.configs.experimental"],
9187
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-pick-index-signature"
9188
+ },
9189
+ messages: {
9190
+ preferPickIndexSignature: "Prefer `PickIndexSignature<ObjectType>` from type-fest over manual mapped types that keep only index signatures."
9191
+ },
9192
+ schema: [],
9193
+ type: "suggestion"
9194
+ },
9195
+ name: "prefer-type-fest-pick-index-signature"
9196
+ });
9197
+ var prefer_type_fest_pick_index_signature_default = preferTypeFestPickIndexSignatureRule;
9198
+
8463
9199
  // dist/rules/prefer-type-fest-primitive.js
8464
9200
  var import_utils2 = require("@typescript-eslint/utils");
8465
9201
  var primitiveKeywordTypes = [
@@ -8533,7 +9269,7 @@ var preferTypeFestPrimitiveRule = createTypedRule({
8533
9269
  var prefer_type_fest_primitive_default = preferTypeFestPrimitiveRule;
8534
9270
 
8535
9271
  // dist/rules/prefer-type-fest-promisable.js
8536
- var import_ts_extras37 = require("ts-extras");
9272
+ var import_ts_extras38 = require("ts-extras");
8537
9273
  var PROMISABLE_TYPE_NAME = "Promisable";
8538
9274
  var PROMISE_TYPE_NAME = "Promise";
8539
9275
  var promisableAliasReplacements = {
@@ -8549,10 +9285,10 @@ var getPromiseInnerType = (node) => {
8549
9285
  return null;
8550
9286
  }
8551
9287
  const typeArguments = node.typeArguments?.params;
8552
- if (!(0, import_ts_extras37.isDefined)(typeArguments)) {
9288
+ if (!(0, import_ts_extras38.isDefined)(typeArguments)) {
8553
9289
  return null;
8554
9290
  }
8555
- return (0, import_ts_extras37.arrayFirst)(typeArguments) ?? null;
9291
+ return (0, import_ts_extras38.arrayFirst)(typeArguments) ?? null;
8556
9292
  };
8557
9293
  var preferTypeFestPromisableRule = createTypedRule({
8558
9294
  create(context, [options] = defaultOptions3) {
@@ -9314,6 +10050,49 @@ var preferTypeFestSetRequiredRule = createTypedRule({
9314
10050
  });
9315
10051
  var prefer_type_fest_set_required_default = preferTypeFestSetRequiredRule;
9316
10052
 
10053
+ // dist/rules/prefer-type-fest-set-return-type.js
10054
+ var preferTypeFestSetReturnTypeRule = createTypedRule({
10055
+ create(context) {
10056
+ return {
10057
+ TSFunctionType(node) {
10058
+ const functionType = getParametersFunctionArgumentFromFunctionType(node);
10059
+ const returnType = node.returnType?.typeAnnotation;
10060
+ if (functionType === null || returnType === void 0) {
10061
+ return;
10062
+ }
10063
+ if (isReturnTypeReferenceForFunction(returnType, functionType) || isPromiseAwaitedReturnTypeReferenceForFunction(returnType, functionType)) {
10064
+ return;
10065
+ }
10066
+ reportWithOptionalFix({
10067
+ context,
10068
+ fix: null,
10069
+ messageId: "preferSetReturnType",
10070
+ node
10071
+ });
10072
+ }
10073
+ };
10074
+ },
10075
+ defaultOptions: [],
10076
+ meta: {
10077
+ deprecated: false,
10078
+ docs: {
10079
+ description: "require TypeFest SetReturnType over direct function-type wrappers of the form (...args: Parameters<F>) => R.",
10080
+ frozen: false,
10081
+ recommended: false,
10082
+ requiresTypeChecking: false,
10083
+ typefestConfigs: ["typefest.configs.experimental"],
10084
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-set-return-type"
10085
+ },
10086
+ messages: {
10087
+ preferSetReturnType: "Prefer `SetReturnType<Function, TypeToReturn>` from type-fest over direct function-type wrappers like `(...args: Parameters<Function>) => TypeToReturn`."
10088
+ },
10089
+ schema: [],
10090
+ type: "suggestion"
10091
+ },
10092
+ name: "prefer-type-fest-set-return-type"
10093
+ });
10094
+ var prefer_type_fest_set_return_type_default = preferTypeFestSetReturnTypeRule;
10095
+
9317
10096
  // dist/rules/prefer-type-fest-simplify.js
9318
10097
  var simplifyAliasReplacements = {
9319
10098
  Expand: "Simplify",
@@ -9373,6 +10152,67 @@ var preferTypeFestSimplifyRule = createTypedRule({
9373
10152
  });
9374
10153
  var prefer_type_fest_simplify_default = preferTypeFestSimplifyRule;
9375
10154
 
10155
+ // dist/rules/prefer-type-fest-stringified.js
10156
+ var import_ts_extras39 = require("ts-extras");
10157
+ var hasStringifiedMappedTypeShape = (node) => {
10158
+ if (node.readonly !== false && (0, import_ts_extras39.isDefined)(node.readonly)) {
10159
+ return false;
10160
+ }
10161
+ if (node.optional !== false && (0, import_ts_extras39.isDefined)(node.optional)) {
10162
+ return false;
10163
+ }
10164
+ if (node.nameType !== null) {
10165
+ return false;
10166
+ }
10167
+ if (node.key.type !== "Identifier") {
10168
+ return false;
10169
+ }
10170
+ const { constraint } = node;
10171
+ if (constraint?.type !== "TSTypeOperator") {
10172
+ return false;
10173
+ }
10174
+ if (constraint.operator !== "keyof") {
10175
+ return false;
10176
+ }
10177
+ return node.typeAnnotation?.type === "TSStringKeyword";
10178
+ };
10179
+ var preferTypeFestStringifiedRule = createTypedRule({
10180
+ create(context) {
10181
+ return {
10182
+ TSMappedType(node) {
10183
+ if (!hasStringifiedMappedTypeShape(node)) {
10184
+ return;
10185
+ }
10186
+ reportWithOptionalFix({
10187
+ context,
10188
+ fix: null,
10189
+ messageId: "preferStringified",
10190
+ node
10191
+ });
10192
+ }
10193
+ };
10194
+ },
10195
+ defaultOptions: [],
10196
+ meta: {
10197
+ deprecated: false,
10198
+ docs: {
10199
+ description: "require TypeFest Stringified over manual mapped types of the form { [K in keyof T]: string }.",
10200
+ frozen: false,
10201
+ recommended: false,
10202
+ requiresTypeChecking: false,
10203
+ typefestConfigs: ["typefest.configs.experimental"],
10204
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-stringified"
10205
+ },
10206
+ messages: {
10207
+ preferStringified: "Prefer `Stringified<T>` from type-fest over manual mapped types of the form `{ [K in keyof T]: string }`."
10208
+ },
10209
+ schema: [],
10210
+ type: "suggestion"
10211
+ },
10212
+ name: "prefer-type-fest-stringified"
10213
+ });
10214
+ var prefer_type_fest_stringified_default = preferTypeFestStringifiedRule;
10215
+
9376
10216
  // dist/rules/prefer-type-fest-tagged-brands.js
9377
10217
  var BRAND_PROPERTY_NAMES = /* @__PURE__ */ new Set([
9378
10218
  "__brand",
@@ -9614,7 +10454,7 @@ var preferTypeFestTupleOfRule = createTypedRule({
9614
10454
  var prefer_type_fest_tuple_of_default = preferTypeFestTupleOfRule;
9615
10455
 
9616
10456
  // dist/rules/prefer-type-fest-union-member.js
9617
- var import_ts_extras38 = require("ts-extras");
10457
+ var import_ts_extras40 = require("ts-extras");
9618
10458
  var UNION_MEMBER_TYPE_NAME = "UnionMember";
9619
10459
  var UNION_TO_INTERSECTION_TYPE_NAME = "UnionToIntersection";
9620
10460
  var IS_NEVER_TYPE_NAME = "IsNever";
@@ -9645,7 +10485,7 @@ var getUnionArgumentTextFromExtractor = ({ node, sourceCode }) => {
9645
10485
  if (!isIdentifierTypeReferenceNamed(node.checkType, UNION_TO_INTERSECTION_TYPE_NAME)) {
9646
10486
  return null;
9647
10487
  }
9648
- const extractorArgument = (0, import_ts_extras38.arrayFirst)(node.checkType.typeArguments?.params ?? []);
10488
+ const extractorArgument = (0, import_ts_extras40.arrayFirst)(node.checkType.typeArguments?.params ?? []);
9649
10489
  if (!extractorArgument) {
9650
10490
  return null;
9651
10491
  }
@@ -9680,7 +10520,7 @@ var getUnionMemberEquivalentArgumentText = ({ node, sourceCode }) => {
9680
10520
  if (!isIdentifierTypeReferenceNamed(node.checkType, IS_NEVER_TYPE_NAME) || !isBooleanLiteralType(node.extendsType, true) || node.trueType.type !== "TSNeverKeyword") {
9681
10521
  return null;
9682
10522
  }
9683
- const guardedArgument = (0, import_ts_extras38.arrayFirst)(node.checkType.typeArguments?.params ?? []);
10523
+ const guardedArgument = (0, import_ts_extras40.arrayFirst)(node.checkType.typeArguments?.params ?? []);
9684
10524
  if (!guardedArgument) {
9685
10525
  return null;
9686
10526
  }
@@ -9743,6 +10583,102 @@ var preferTypeFestUnionMemberRule = createTypedRule({
9743
10583
  });
9744
10584
  var prefer_type_fest_union_member_default = preferTypeFestUnionMemberRule;
9745
10585
 
10586
+ // dist/rules/prefer-type-fest-union-to-intersection.js
10587
+ var isDistributiveConditionalExtendsType3 = (node) => {
10588
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
10589
+ return normalizedNode.type === "TSAnyKeyword" || normalizedNode.type === "TSUnknownKeyword";
10590
+ };
10591
+ var getSingleFunctionParameterType = (node) => {
10592
+ if (node.params.length !== 1) {
10593
+ return null;
10594
+ }
10595
+ const [onlyParameter] = node.params;
10596
+ if (onlyParameter?.type !== "Identifier" || onlyParameter.typeAnnotation === void 0) {
10597
+ return null;
10598
+ }
10599
+ return unwrapParenthesizedTypeNode(onlyParameter.typeAnnotation.typeAnnotation);
10600
+ };
10601
+ var matchesUnionToIntersectionTrueType = (node, inferredTypeParameterName, unionType) => {
10602
+ const normalizedNode = unwrapParenthesizedTypeNode(node);
10603
+ if (normalizedNode.type === "TSTypeReference" && normalizedNode.typeName.type === "Identifier" && normalizedNode.typeName.name === inferredTypeParameterName) {
10604
+ return true;
10605
+ }
10606
+ if (normalizedNode.type !== "TSIntersectionType" || normalizedNode.types.length !== 2) {
10607
+ return false;
10608
+ }
10609
+ const [leftType, rightType] = normalizedNode.types;
10610
+ if (leftType === void 0 || rightType === void 0) {
10611
+ return false;
10612
+ }
10613
+ const isInferredIdentifier = (typeNode) => typeNode.type === "TSTypeReference" && typeNode.typeName.type === "Identifier" && typeNode.typeName.name === inferredTypeParameterName;
10614
+ return isInferredIdentifier(leftType) && areEquivalentTypeNodes(unwrapParenthesizedTypeNode(rightType), unwrapParenthesizedTypeNode(unionType)) || isInferredIdentifier(rightType) && areEquivalentTypeNodes(unwrapParenthesizedTypeNode(leftType), unwrapParenthesizedTypeNode(unionType));
10615
+ };
10616
+ var isUnionToIntersectionEquivalent = (node) => {
10617
+ if (node.falseType.type !== "TSNeverKeyword") {
10618
+ return false;
10619
+ }
10620
+ const distributedWrapper = unwrapParenthesizedTypeNode(node.checkType);
10621
+ if (distributedWrapper.type !== "TSConditionalType") {
10622
+ return false;
10623
+ }
10624
+ if (distributedWrapper.falseType.type !== "TSNeverKeyword" || !isDistributiveConditionalExtendsType3(distributedWrapper.extendsType)) {
10625
+ return false;
10626
+ }
10627
+ const distributedTrueType = unwrapParenthesizedTypeNode(distributedWrapper.trueType);
10628
+ if (distributedTrueType.type !== "TSFunctionType") {
10629
+ return false;
10630
+ }
10631
+ const distributedParameterType = getSingleFunctionParameterType(distributedTrueType);
10632
+ if (distributedParameterType === null || !areEquivalentTypeNodes(distributedParameterType, unwrapParenthesizedTypeNode(distributedWrapper.checkType))) {
10633
+ return false;
10634
+ }
10635
+ const extractorFunctionType = unwrapParenthesizedTypeNode(node.extendsType);
10636
+ if (extractorFunctionType.type !== "TSFunctionType") {
10637
+ return false;
10638
+ }
10639
+ const extractorParameterType = getSingleFunctionParameterType(extractorFunctionType);
10640
+ if (extractorParameterType?.type !== "TSInferType") {
10641
+ return false;
10642
+ }
10643
+ return matchesUnionToIntersectionTrueType(node.trueType, extractorParameterType.typeParameter.name.name, distributedWrapper.checkType);
10644
+ };
10645
+ var preferTypeFestUnionToIntersectionRule = createTypedRule({
10646
+ create(context) {
10647
+ return {
10648
+ TSConditionalType(node) {
10649
+ if (!isUnionToIntersectionEquivalent(node)) {
10650
+ return;
10651
+ }
10652
+ reportWithOptionalFix({
10653
+ context,
10654
+ fix: null,
10655
+ messageId: "preferUnionToIntersection",
10656
+ node
10657
+ });
10658
+ }
10659
+ };
10660
+ },
10661
+ defaultOptions: [],
10662
+ meta: {
10663
+ deprecated: false,
10664
+ docs: {
10665
+ description: "require TypeFest UnionToIntersection over custom distributive conditional helpers that turn unions into intersections.",
10666
+ frozen: false,
10667
+ recommended: false,
10668
+ requiresTypeChecking: false,
10669
+ typefestConfigs: ["typefest.configs.experimental"],
10670
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-union-to-intersection"
10671
+ },
10672
+ messages: {
10673
+ preferUnionToIntersection: "Prefer `UnionToIntersection<Union>` from type-fest over custom distributive conditional helpers that convert a union into an intersection."
10674
+ },
10675
+ schema: [],
10676
+ type: "suggestion"
10677
+ },
10678
+ name: "prefer-type-fest-union-to-intersection"
10679
+ });
10680
+ var prefer_type_fest_union_to_intersection_default = preferTypeFestUnionToIntersectionRule;
10681
+
9746
10682
  // dist/rules/prefer-type-fest-union-to-tuple.js
9747
10683
  var unionToTupleAliasReplacements = {
9748
10684
  TupleFromUnion: "UnionToTuple",
@@ -10350,6 +11286,7 @@ var typefestRuleRegistry = {
10350
11286
  "prefer-ts-extras-object-has-in": prefer_ts_extras_object_has_in_default,
10351
11287
  "prefer-ts-extras-object-has-own": prefer_ts_extras_object_has_own_default,
10352
11288
  "prefer-ts-extras-object-keys": prefer_ts_extras_object_keys_default,
11289
+ "prefer-ts-extras-object-map-values": prefer_ts_extras_object_map_values_default,
10353
11290
  "prefer-ts-extras-object-values": prefer_ts_extras_object_values_default,
10354
11291
  "prefer-ts-extras-safe-cast-to": prefer_ts_extras_safe_cast_to_default,
10355
11292
  "prefer-ts-extras-set-has": prefer_ts_extras_set_has_default,
@@ -10359,9 +11296,14 @@ var typefestRuleRegistry = {
10359
11296
  "prefer-type-fest-array-length": prefer_type_fest_array_length_default,
10360
11297
  "prefer-type-fest-arrayable": prefer_type_fest_arrayable_default,
10361
11298
  "prefer-type-fest-async-return-type": prefer_type_fest_async_return_type_default,
11299
+ "prefer-type-fest-asyncify": prefer_type_fest_asyncify_default,
11300
+ "prefer-type-fest-conditional-except": prefer_type_fest_conditional_except_default,
11301
+ "prefer-type-fest-conditional-keys": prefer_type_fest_conditional_keys_default,
10362
11302
  "prefer-type-fest-conditional-pick": prefer_type_fest_conditional_pick_default,
10363
11303
  "prefer-type-fest-conditional-pick-deep": prefer_type_fest_conditional_pick_deep_default,
10364
11304
  "prefer-type-fest-constructor": prefer_type_fest_constructor_default,
11305
+ "prefer-type-fest-distributed-omit": prefer_type_fest_distributed_omit_default,
11306
+ "prefer-type-fest-distributed-pick": prefer_type_fest_distributed_pick_default,
10365
11307
  "prefer-type-fest-except": prefer_type_fest_except_default,
10366
11308
  "prefer-type-fest-if": prefer_type_fest_if_default,
10367
11309
  "prefer-type-fest-iterable-element": prefer_type_fest_iterable_element_default,
@@ -10373,12 +11315,14 @@ var typefestRuleRegistry = {
10373
11315
  "prefer-type-fest-less-than": prefer_type_fest_less_than_default,
10374
11316
  "prefer-type-fest-less-than-or-equal": prefer_type_fest_less_than_or_equal_default,
10375
11317
  "prefer-type-fest-literal-union": prefer_type_fest_literal_union_default,
11318
+ "prefer-type-fest-merge": prefer_type_fest_merge_default,
10376
11319
  "prefer-type-fest-merge-exclusive": prefer_type_fest_merge_exclusive_default,
10377
11320
  "prefer-type-fest-non-empty-tuple": prefer_type_fest_non_empty_tuple_default,
10378
11321
  "prefer-type-fest-omit-index-signature": prefer_type_fest_omit_index_signature_default,
10379
11322
  "prefer-type-fest-optional": prefer_type_fest_optional_default,
10380
11323
  "prefer-type-fest-or-all": prefer_type_fest_or_all_default,
10381
11324
  "prefer-type-fest-partial-deep": prefer_type_fest_partial_deep_default,
11325
+ "prefer-type-fest-pick-index-signature": prefer_type_fest_pick_index_signature_default,
10382
11326
  "prefer-type-fest-primitive": prefer_type_fest_primitive_default,
10383
11327
  "prefer-type-fest-promisable": prefer_type_fest_promisable_default,
10384
11328
  "prefer-type-fest-readonly-deep": prefer_type_fest_readonly_deep_default,
@@ -10392,10 +11336,13 @@ var typefestRuleRegistry = {
10392
11336
  "prefer-type-fest-set-optional": prefer_type_fest_set_optional_default,
10393
11337
  "prefer-type-fest-set-readonly": prefer_type_fest_set_readonly_default,
10394
11338
  "prefer-type-fest-set-required": prefer_type_fest_set_required_default,
11339
+ "prefer-type-fest-set-return-type": prefer_type_fest_set_return_type_default,
10395
11340
  "prefer-type-fest-simplify": prefer_type_fest_simplify_default,
11341
+ "prefer-type-fest-stringified": prefer_type_fest_stringified_default,
10396
11342
  "prefer-type-fest-tagged-brands": prefer_type_fest_tagged_brands_default,
10397
11343
  "prefer-type-fest-tuple-of": prefer_type_fest_tuple_of_default,
10398
11344
  "prefer-type-fest-union-member": prefer_type_fest_union_member_default,
11345
+ "prefer-type-fest-union-to-intersection": prefer_type_fest_union_to_intersection_default,
10399
11346
  "prefer-type-fest-union-to-tuple": prefer_type_fest_union_to_tuple_default,
10400
11347
  "prefer-type-fest-unknown-array": prefer_type_fest_unknown_array_default,
10401
11348
  "prefer-type-fest-unknown-map": prefer_type_fest_unknown_map_default,
@@ -10418,7 +11365,7 @@ function getPackageVersion(pkg) {
10418
11365
  const version = Reflect.get(pkg, "version");
10419
11366
  return typeof version === "string" ? version : "0.0.0";
10420
11367
  }
10421
- var packageJsonValue = (0, import_ts_extras39.safeCastTo)(package_default);
11368
+ var packageJsonValue = (0, import_ts_extras41.safeCastTo)(package_default);
10422
11369
  var typeScriptParserValue = import_parser3.default;
10423
11370
  var defaultParserOptions = {
10424
11371
  ecmaVersion: "latest",
@@ -10426,10 +11373,10 @@ var defaultParserOptions = {
10426
11373
  };
10427
11374
  var normalizeParserOptions = (parserOptions) => parserOptions !== null && typeof parserOptions === "object" && !Array.isArray(parserOptions) ? { ...parserOptions } : { ...defaultParserOptions };
10428
11375
  var typefestEslintRules = typefestRules;
10429
- var isTypefestRuleName = (value) => (0, import_ts_extras39.objectHasIn)(typefestRules, value);
11376
+ var isTypefestRuleName = (value) => (0, import_ts_extras41.objectHasIn)(typefestRules, value);
10430
11377
  var typefestRuleEntries = (() => {
10431
11378
  const entries = [];
10432
- for (const [ruleName] of (0, import_ts_extras39.objectEntries)(typefestRules)) {
11379
+ for (const [ruleName] of (0, import_ts_extras41.objectEntries)(typefestRules)) {
10433
11380
  if (!isTypefestRuleName(ruleName)) {
10434
11381
  continue;
10435
11382
  }
@@ -10456,7 +11403,7 @@ var derivePresetRuleNamesByConfig = () => {
10456
11403
  const presetRuleNamesByConfig2 = createEmptyPresetRuleMap();
10457
11404
  for (const [ruleName] of typefestRuleEntries) {
10458
11405
  const configNames = rulePresetMembership[ruleName];
10459
- if (!(0, import_ts_extras39.isDefined)(configNames) || (0, import_ts_extras39.isEmpty)(configNames)) {
11406
+ if (!(0, import_ts_extras41.isDefined)(configNames) || (0, import_ts_extras41.isEmpty)(configNames)) {
10460
11407
  throw new TypeError(`Rule '${ruleName}' is missing preset membership metadata.`);
10461
11408
  }
10462
11409
  for (const configName of configNames) {
@@ -10465,6 +11412,7 @@ var derivePresetRuleNamesByConfig = () => {
10465
11412
  }
10466
11413
  return {
10467
11414
  all: dedupeRuleNames(presetRuleNamesByConfig2.all),
11415
+ experimental: dedupeRuleNames(presetRuleNamesByConfig2.experimental),
10468
11416
  minimal: dedupeRuleNames(presetRuleNamesByConfig2.minimal),
10469
11417
  recommended: dedupeRuleNames(presetRuleNamesByConfig2.recommended),
10470
11418
  "recommended-type-checked": dedupeRuleNames(presetRuleNamesByConfig2["recommended-type-checked"]),
@@ -10483,7 +11431,7 @@ function errorRulesFor(ruleNames) {
10483
11431
  var presetRuleNamesByConfig = derivePresetRuleNamesByConfig();
10484
11432
  var recommendedRuleNames = [];
10485
11433
  for (const ruleName of presetRuleNamesByConfig.recommended) {
10486
- if ((0, import_ts_extras39.setHas)(typeCheckedRuleNames, ruleName)) {
11434
+ if ((0, import_ts_extras41.setHas)(typeCheckedRuleNames, ruleName)) {
10487
11435
  continue;
10488
11436
  }
10489
11437
  recommendedRuleNames.push(ruleName);
@@ -10494,6 +11442,10 @@ var recommendedTypeCheckedRuleNames = dedupeRuleNames([
10494
11442
  ]);
10495
11443
  var effectivePresetRuleNamesByConfig = {
10496
11444
  ...presetRuleNamesByConfig,
11445
+ experimental: dedupeRuleNames([
11446
+ ...presetRuleNamesByConfig.all,
11447
+ ...presetRuleNamesByConfig.experimental
11448
+ ]),
10497
11449
  recommended: recommendedRuleNames,
10498
11450
  "recommended-type-checked": recommendedTypeCheckedRuleNames
10499
11451
  };
@@ -10501,7 +11453,7 @@ function withTypefestPlugin(config, plugin, options) {
10501
11453
  const existingLanguageOptions = config.languageOptions ?? {};
10502
11454
  const existingParserOptions = existingLanguageOptions["parserOptions"];
10503
11455
  const parserOptions = normalizeParserOptions(existingParserOptions);
10504
- if (options.requiresTypeChecking && !(0, import_ts_extras39.objectHasIn)(parserOptions, "projectService")) {
11456
+ if (options.requiresTypeChecking && !(0, import_ts_extras41.objectHasIn)(parserOptions, "projectService")) {
10505
11457
  Reflect.set(parserOptions, "projectService", true);
10506
11458
  }
10507
11459
  const languageOptions = {