eslint-plugin-typefest 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +6 -0
  2. package/dist/_internal/rule-catalog.d.ts.map +1 -1
  3. package/dist/_internal/rule-catalog.js +6 -0
  4. package/dist/_internal/rule-catalog.js.map +1 -1
  5. package/dist/_internal/rules-registry.d.ts.map +1 -1
  6. package/dist/_internal/rules-registry.js +12 -0
  7. package/dist/_internal/rules-registry.js.map +1 -1
  8. package/dist/plugin.cjs +488 -53
  9. package/dist/plugin.cjs.map +4 -4
  10. package/dist/rules/prefer-ts-extras-assert-never.d.ts +13 -0
  11. package/dist/rules/prefer-ts-extras-assert-never.d.ts.map +1 -0
  12. package/dist/rules/prefer-ts-extras-assert-never.js +116 -0
  13. package/dist/rules/prefer-ts-extras-assert-never.js.map +1 -0
  14. package/dist/rules/prefer-ts-extras-is-property-defined.d.ts +13 -0
  15. package/dist/rules/prefer-ts-extras-is-property-defined.d.ts.map +1 -0
  16. package/dist/rules/prefer-ts-extras-is-property-defined.js +160 -0
  17. package/dist/rules/prefer-ts-extras-is-property-defined.js.map +1 -0
  18. package/dist/rules/prefer-ts-extras-is-property-present.d.ts +13 -0
  19. package/dist/rules/prefer-ts-extras-is-property-present.d.ts.map +1 -0
  20. package/dist/rules/prefer-ts-extras-is-property-present.js +114 -0
  21. package/dist/rules/prefer-ts-extras-is-property-present.js.map +1 -0
  22. package/dist/rules/prefer-type-fest-absolute.d.ts +13 -0
  23. package/dist/rules/prefer-type-fest-absolute.d.ts.map +1 -0
  24. package/dist/rules/prefer-type-fest-absolute.js +67 -0
  25. package/dist/rules/prefer-type-fest-absolute.js.map +1 -0
  26. package/dist/rules/prefer-type-fest-non-nullable-deep.d.ts +13 -0
  27. package/dist/rules/prefer-type-fest-non-nullable-deep.d.ts.map +1 -0
  28. package/dist/rules/prefer-type-fest-non-nullable-deep.js +58 -0
  29. package/dist/rules/prefer-type-fest-non-nullable-deep.js.map +1 -0
  30. package/dist/rules/prefer-type-fest-union-length.d.ts +13 -0
  31. package/dist/rules/prefer-type-fest-union-length.d.ts.map +1 -0
  32. package/dist/rules/prefer-type-fest-union-length.js +75 -0
  33. package/dist/rules/prefer-type-fest-union-length.js.map +1 -0
  34. package/docs/rules/prefer-ts-extras-assert-never.md +112 -0
  35. package/docs/rules/prefer-ts-extras-is-property-defined.md +119 -0
  36. package/docs/rules/prefer-ts-extras-is-property-present.md +118 -0
  37. package/docs/rules/prefer-type-fest-absolute.md +99 -0
  38. package/docs/rules/prefer-type-fest-non-nullable-deep.md +105 -0
  39. package/docs/rules/prefer-type-fest-union-length.md +100 -0
  40. package/docs/rules/presets/all.md +6 -0
  41. package/docs/rules/presets/experimental.md +6 -0
  42. package/docs/rules/presets/index.md +6 -0
  43. package/docs/rules/presets/minimal.md +2 -0
  44. package/docs/rules/presets/recommended-type-checked.md +6 -0
  45. package/docs/rules/presets/recommended.md +6 -0
  46. package/docs/rules/presets/strict.md +6 -0
  47. package/docs/rules/presets/ts-extras-type-guards.md +3 -0
  48. package/docs/rules/presets/type-fest-types.md +3 -0
  49. package/package.json +26 -21
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_extras41 = require("ts-extras");
37
+ var import_ts_extras43 = 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.2.0",
43
+ version: "1.2.2",
44
44
  private: false,
45
45
  description: "ESLint rules for adopting type-fest and ts-extras conventions.",
46
46
  keywords: [
@@ -187,6 +187,7 @@ var package_default = {
187
187
  "lint:knip:unused:exports": "npm run knip -- --dependencies --exports",
188
188
  "lint:leaves": "npm run madge:leaves",
189
189
  "lint:metrics": "npm run sloc",
190
+ "lint:nocache": "cross-env NODE_OPTIONS=--max_old_space_size=16384 eslint .",
190
191
  "lint:node-version-files": "node scripts/sync-node-version-files.mjs --check",
191
192
  "lint:orphans": "npm run madge:orphans",
192
193
  "lint:package": 'npm run lint:node-version-files && npm run lint:package-sort && npm run lint:packagelintrc && echo "Package.json lint done!"',
@@ -214,9 +215,10 @@ var package_default = {
214
215
  "open:coverage": "open-cli coverage/index.html",
215
216
  prepublishOnly: "npm run release:check",
216
217
  "release:check": "npm run release:verify",
217
- "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 run lint:package:strict",
218
+ "release:verify": "cross-env NODE_OPTIONS= npm run build && cross-env NODE_OPTIONS= npm run lint:nocache && 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 run lint:package:strict",
218
219
  "remark:fix": 'remark --rc-path .remarkrc.mjs --silently-ignore --ignore-path .remarkignore --frail --quiet --output -- "*.{md,mdx}" "docs/**/*.{md,mdx}"',
219
220
  "remark:test-config": 'remark --rc-path .remarkrc.mjs --silently-ignore --ignore-path .remarkignore --frail "README.md"',
221
+ size: "size-limit",
220
222
  "sync:node-version-files": "node scripts/sync-node-version-files.mjs",
221
223
  "sync:peer-eslint-range": "node scripts/sync-peer-eslint-range.mjs",
222
224
  "sync:presets-rules-matrix": "node scripts/sync-presets-rules-matrix.mjs",
@@ -258,19 +260,19 @@ var package_default = {
258
260
  "@typescript-eslint/parser": "^8.58.2",
259
261
  "@typescript-eslint/type-utils": "^8.58.2",
260
262
  "@typescript-eslint/utils": "^8.58.2",
261
- "ts-extras": "^0.19.0",
262
- "type-fest": "^5.5.0"
263
+ "ts-extras": "^1.0.0",
264
+ "type-fest": "^5.6.0"
263
265
  },
264
266
  devDependencies: {
265
267
  "@arethetypeswrong/cli": "^0.18.2",
266
268
  "@csstools/stylelint-formatter-github": "^2.0.0",
267
269
  "@docusaurus/eslint-plugin": "^3.10.0",
268
270
  "@double-great/remark-lint-alt-text": "^1.1.1",
269
- "@double-great/stylelint-a11y": "^3.4.9",
271
+ "@double-great/stylelint-a11y": "^3.4.10",
270
272
  "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1",
271
273
  "@eslint-react/eslint-plugin": "^4.2.3",
272
274
  "@eslint/config-helpers": "^0.5.5",
273
- "@eslint/config-inspector": "^1.5.0",
275
+ "@eslint/config-inspector": "^2.0.0",
274
276
  "@eslint/css": "^1.1.0",
275
277
  "@eslint/js": "^10.0.1",
276
278
  "@eslint/json": "^1.2.0",
@@ -292,6 +294,7 @@ var package_default = {
292
294
  "@secretlint/secretlint-rule-privatekey": "^11.7.1",
293
295
  "@secretlint/secretlint-rule-secp256k1-privatekey": "^11.7.1",
294
296
  "@secretlint/types": "^11.7.1",
297
+ "@size-limit/file": "^12.1.0",
295
298
  "@softonus/prettier-plugin-duplicate-remover": "^1.1.2",
296
299
  "@stryker-ignorer/console-all": "^0.3.2",
297
300
  "@stryker-mutator/core": "^9.6.1",
@@ -318,7 +321,7 @@ var package_default = {
318
321
  "@typescript-eslint/rule-tester": "^8.58.2",
319
322
  "@typpi/eslint-plugin-vite": "^1.0.12",
320
323
  "@vitest/coverage-v8": "^4.1.4",
321
- "@vitest/eslint-plugin": "^1.6.15",
324
+ "@vitest/eslint-plugin": "^1.6.16",
322
325
  "@vitest/ui": "^4.1.4",
323
326
  actionlint: "^2.0.6",
324
327
  "all-contributors-cli": "^6.26.1",
@@ -328,20 +331,20 @@ var package_default = {
328
331
  "cross-env": "^10.1.0",
329
332
  depcheck: "^1.4.7",
330
333
  "detect-secrets": "^1.0.6",
331
- eslint: "^10.2.0",
334
+ eslint: "^10.2.1",
332
335
  "eslint-config-flat-gitignore": "^2.3.0",
333
336
  "eslint-config-prettier": "^10.1.8",
334
337
  "eslint-formatter-unix": "^9.0.1",
335
338
  "eslint-import-resolver-typescript": "^4.4.4",
336
339
  "eslint-plugin-array-func": "^5.1.1",
337
340
  "eslint-plugin-canonical": "^5.1.3",
338
- "eslint-plugin-case-police": "^2.2.0",
341
+ "eslint-plugin-case-police": "^2.2.1",
339
342
  "eslint-plugin-comment-length": "^2.3.0",
340
343
  "eslint-plugin-copilot": "^1.0.8",
341
344
  "eslint-plugin-css-modules": "^2.12.0",
342
345
  "eslint-plugin-de-morgan": "^2.1.1",
343
346
  "eslint-plugin-depend": "^1.5.0",
344
- "eslint-plugin-docusaurus-2": "^0.1.3",
347
+ "eslint-plugin-docusaurus-2": "^0.1.4",
345
348
  "eslint-plugin-eslint-plugin": "^7.3.2",
346
349
  "eslint-plugin-etc-misc": "^1.0.6",
347
350
  "eslint-plugin-file-progress-2": "^5.0.1",
@@ -373,21 +376,21 @@ var package_default = {
373
376
  "eslint-plugin-require-jsdoc": "^1.0.4",
374
377
  "eslint-plugin-sdl-2": "^1.0.6",
375
378
  "eslint-plugin-security": "^4.0.0",
376
- "eslint-plugin-sonarjs": "^4.0.2",
377
- "eslint-plugin-stylelint-2": "^1.0.10",
379
+ "eslint-plugin-sonarjs": "^4.0.3",
380
+ "eslint-plugin-stylelint-2": "^1.0.14",
378
381
  "eslint-plugin-testing-library": "^7.16.2",
379
382
  "eslint-plugin-toml": "^1.3.1",
380
383
  "eslint-plugin-tsdoc": "^0.5.2",
381
384
  "eslint-plugin-tsdoc-require-2": "^1.0.9",
382
385
  "eslint-plugin-typedoc": "^1.1.4",
383
- "eslint-plugin-typefest": "^1.0.10",
386
+ "eslint-plugin-typefest": "^1.2.1",
384
387
  "eslint-plugin-undefined-css-classes": "^0.1.5",
385
388
  "eslint-plugin-unicorn": "^64.0.0",
386
389
  "eslint-plugin-unused-imports": "^4.4.1",
387
390
  "eslint-plugin-write-good-comments-2": "^1.0.6",
388
391
  "eslint-plugin-yml": "^3.3.1",
389
392
  "eslint-rule-benchmark": "^0.8.0",
390
- "fast-check": "^4.6.0",
393
+ "fast-check": "^4.7.0",
391
394
  "git-cliff": "^2.12.0",
392
395
  "gitleaks-secret-scanner": "^2.1.1",
393
396
  globals: "^17.5.0",
@@ -398,10 +401,10 @@ var package_default = {
398
401
  leasot: "^14.4.0",
399
402
  madge: "^8.0.0",
400
403
  "markdown-link-check": "^3.14.2",
401
- "npm-check-updates": "^20.0.2",
404
+ "npm-check-updates": "^21.0.2",
402
405
  "npm-package-json-lint": "^10.2.1",
403
406
  picocolors: "^1.1.1",
404
- postcss: "^8.5.9",
407
+ postcss: "^8.5.10",
405
408
  "postcss-assets": "^6.0.0",
406
409
  "postcss-clamp": "^4.1.0",
407
410
  "postcss-combine-duplicated-selectors": "^10.0.3",
@@ -418,7 +421,7 @@ var package_default = {
418
421
  "postcss-styled-jsx": "^1.0.1",
419
422
  "postcss-styled-syntax": "^0.7.1",
420
423
  "postcss-viewport-height-correction": "^1.1.1",
421
- prettier: "^3.8.2",
424
+ prettier: "^3.8.3",
422
425
  "prettier-plugin-ini": "^1.3.0",
423
426
  "prettier-plugin-interpolated-html-tags": "^2.0.1",
424
427
  "prettier-plugin-jsdoc": "^1.8.0",
@@ -539,15 +542,16 @@ var package_default = {
539
542
  "remark-wiki-link": "^2.0.1",
540
543
  rimraf: "^6.1.3",
541
544
  secretlint: "^11.7.1",
545
+ "size-limit": "^12.1.0",
542
546
  sloc: "^0.3.2",
543
547
  "sort-package-json": "^3.6.1",
544
- stylelint: "^17.7.0",
548
+ stylelint: "^17.8.0",
545
549
  "stylelint-actions-formatters": "^16.3.1",
546
550
  "stylelint-checkstyle-formatter": "^0.1.2",
547
551
  "stylelint-codeframe-formatter": "^1.2.0",
548
552
  "stylelint-config-alphabetical-order": "^2.0.0",
549
553
  "stylelint-config-idiomatic-order": "^10.0.0",
550
- "stylelint-config-inspector": "^2.0.3",
554
+ "stylelint-config-inspector": "^2.1.1",
551
555
  "stylelint-config-recess-order": "^7.7.0",
552
556
  "stylelint-config-recommended": "^18.0.0",
553
557
  "stylelint-config-sass-guidelines": "^13.0.0",
@@ -571,6 +575,7 @@ var package_default = {
571
575
  "stylelint-no-unsupported-browser-features": "^8.1.1",
572
576
  "stylelint-order": "^8.1.1",
573
577
  "stylelint-plugin-defensive-css": "^2.9.0",
578
+ "stylelint-plugin-docusaurus": "^1.0.2",
574
579
  "stylelint-plugin-logical-css": "^2.1.0",
575
580
  "stylelint-plugin-use-baseline": "^1.4.1",
576
581
  "stylelint-prettier": "^5.0.3",
@@ -582,7 +587,7 @@ var package_default = {
582
587
  "toml-eslint-parser": "^1.0.3",
583
588
  "ts-unused-exports": "^11.0.1",
584
589
  typedoc: "^0.28.19",
585
- typescript: "^6.0.2",
590
+ typescript: "^6.0.3",
586
591
  "typescript-eslint": "^8.58.2",
587
592
  typesync: "^0.14.3",
588
593
  vfile: "^6.0.3",
@@ -593,7 +598,7 @@ var package_default = {
593
598
  "yamllint-js": "^0.2.4"
594
599
  },
595
600
  peerDependencies: {
596
- eslint: "^9.0.0 || ^10.2.0",
601
+ eslint: "^9.0.0 || ^10.2.1",
597
602
  typescript: "^5.0.0 || ^6.0.2"
598
603
  },
599
604
  packageManager: "npm@11.12.1",
@@ -2384,7 +2389,13 @@ var orderedRuleNames = [
2384
2389
  "prefer-type-fest-unwrap-tagged",
2385
2390
  "prefer-type-fest-value-of",
2386
2391
  "prefer-type-fest-writable",
2387
- "prefer-type-fest-writable-deep"
2392
+ "prefer-type-fest-writable-deep",
2393
+ "prefer-type-fest-absolute",
2394
+ "prefer-type-fest-non-nullable-deep",
2395
+ "prefer-type-fest-union-length",
2396
+ "prefer-ts-extras-assert-never",
2397
+ "prefer-ts-extras-is-property-defined",
2398
+ "prefer-ts-extras-is-property-present"
2388
2399
  ];
2389
2400
  var toRuleCatalogId = (ruleNumber) => `R${String(ruleNumber).padStart(3, "0")}`;
2390
2401
  var isTypefestRuleNamePattern2 = (ruleName) => ruleName.startsWith("prefer-");
@@ -3634,6 +3645,101 @@ var preferTsExtrasAssertErrorRule = createTypedRule({
3634
3645
  });
3635
3646
  var prefer_ts_extras_assert_error_default = preferTsExtrasAssertErrorRule;
3636
3647
 
3648
+ // dist/rules/prefer-ts-extras-assert-never.js
3649
+ var preferTsExtrasAssertNeverRule = createTypedRule({
3650
+ create(context) {
3651
+ const tsExtrasImports = collectDirectNamedValueImportsFromSource(context.sourceCode, TS_EXTRAS_MODULE_SOURCE);
3652
+ return {
3653
+ VariableDeclaration(node) {
3654
+ if (node.kind !== "const" || node.declarations.length !== 1) {
3655
+ return;
3656
+ }
3657
+ const [declarator] = node.declarations;
3658
+ if (declarator?.id.type !== "Identifier") {
3659
+ return;
3660
+ }
3661
+ const { typeAnnotation } = declarator.id;
3662
+ if (typeAnnotation?.typeAnnotation.type !== "TSNeverKeyword") {
3663
+ return;
3664
+ }
3665
+ const { init } = declarator;
3666
+ if (!init) {
3667
+ return;
3668
+ }
3669
+ const initArgumentText = getFunctionCallArgumentText({
3670
+ argumentNode: init,
3671
+ sourceCode: context.sourceCode
3672
+ });
3673
+ if (initArgumentText === null) {
3674
+ reportWithOptionalFix({
3675
+ context,
3676
+ fix: null,
3677
+ messageId: "preferTsExtrasAssertNever",
3678
+ node
3679
+ });
3680
+ return;
3681
+ }
3682
+ const replacementFix = createSafeValueNodeTextReplacementFix({
3683
+ context,
3684
+ importedName: "assertNever",
3685
+ imports: tsExtrasImports,
3686
+ replacementTextFactory: (replacementName) => `${replacementName}(${initArgumentText})`,
3687
+ reportFixIntent: "suggestion",
3688
+ sourceModuleName: TS_EXTRAS_MODULE_SOURCE,
3689
+ targetNode: node
3690
+ });
3691
+ if (replacementFix === null) {
3692
+ reportWithOptionalFix({
3693
+ context,
3694
+ fix: null,
3695
+ messageId: "preferTsExtrasAssertNever",
3696
+ node
3697
+ });
3698
+ return;
3699
+ }
3700
+ reportWithTypefestPolicy({
3701
+ context,
3702
+ descriptor: {
3703
+ messageId: "preferTsExtrasAssertNever",
3704
+ node,
3705
+ suggest: [
3706
+ {
3707
+ fix: replacementFix,
3708
+ messageId: "suggestTsExtrasAssertNever"
3709
+ }
3710
+ ]
3711
+ }
3712
+ });
3713
+ }
3714
+ };
3715
+ },
3716
+ meta: {
3717
+ deprecated: false,
3718
+ docs: {
3719
+ description: "require ts-extras assertNever over manual `const _: never = value` exhaustiveness checks.",
3720
+ frozen: false,
3721
+ recommended: true,
3722
+ requiresTypeChecking: false,
3723
+ typefestConfigs: [
3724
+ "typefest.configs.recommended",
3725
+ "typefest.configs.strict",
3726
+ "typefest.configs.all",
3727
+ "typefest.configs.ts-extras/type-guards"
3728
+ ],
3729
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-ts-extras-assert-never"
3730
+ },
3731
+ hasSuggestions: true,
3732
+ messages: {
3733
+ preferTsExtrasAssertNever: "Prefer `assertNever` from `ts-extras` over a manual `const _: never` exhaustiveness assertion.",
3734
+ suggestTsExtrasAssertNever: "Replace this manual exhaustiveness check with `assertNever(...)` from `ts-extras`."
3735
+ },
3736
+ schema: [],
3737
+ type: "suggestion"
3738
+ },
3739
+ name: "prefer-ts-extras-assert-never"
3740
+ });
3741
+ var prefer_ts_extras_assert_never_default = preferTsExtrasAssertNeverRule;
3742
+
3637
3743
  // dist/rules/prefer-ts-extras-assert-present.js
3638
3744
  var isNullExpression = (node) => node.type === "Literal" && node.value === null;
3639
3745
  var isUndefinedExpression2 = ({ context, node }) => {
@@ -5353,6 +5459,177 @@ var preferTsExtrasIsPresentRule = createTypedRule({
5353
5459
  });
5354
5460
  var prefer_ts_extras_is_present_default = preferTsExtrasIsPresentRule;
5355
5461
 
5462
+ // dist/rules/prefer-ts-extras-is-property-defined.js
5463
+ var extractTypeofPropertyDefinedCheck = (typeofSide, stringSide, operator, paramName) => {
5464
+ if (operator !== "!==") {
5465
+ return null;
5466
+ }
5467
+ if (typeofSide.type !== "UnaryExpression" || typeofSide.operator !== "typeof") {
5468
+ return null;
5469
+ }
5470
+ const { argument } = typeofSide;
5471
+ if (argument.type !== "MemberExpression" || argument.computed || argument.object.type !== "Identifier" || argument.object.name !== paramName || argument.property.type !== "Identifier") {
5472
+ return null;
5473
+ }
5474
+ if (stringSide.type !== "Literal" || stringSide.value !== "undefined") {
5475
+ return null;
5476
+ }
5477
+ return argument.property.name;
5478
+ };
5479
+ var extractPropertyDefinedGuardBody = (context, body, paramName) => {
5480
+ if (body.type !== "BinaryExpression") {
5481
+ return null;
5482
+ }
5483
+ const { left, operator, right } = body;
5484
+ if (operator !== "!==" && operator !== "!=") {
5485
+ return null;
5486
+ }
5487
+ const typeofLeftResult = extractTypeofPropertyDefinedCheck(left, right, operator, paramName);
5488
+ if (typeofLeftResult !== null) {
5489
+ return typeofLeftResult;
5490
+ }
5491
+ const typeofRightResult = extractTypeofPropertyDefinedCheck(right, left, operator, paramName);
5492
+ if (typeofRightResult !== null) {
5493
+ return typeofRightResult;
5494
+ }
5495
+ if (left.type === "MemberExpression" && !left.computed && left.object.type === "Identifier" && left.object.name === paramName && left.property.type === "Identifier" && isGlobalUndefinedIdentifier(context, right)) {
5496
+ return left.property.name;
5497
+ }
5498
+ if (right.type === "MemberExpression" && !right.computed && right.object.type === "Identifier" && right.object.name === paramName && right.property.type === "Identifier" && isGlobalUndefinedIdentifier(context, left)) {
5499
+ return right.property.name;
5500
+ }
5501
+ return null;
5502
+ };
5503
+ var preferTsExtrasIsPropertyDefinedRule = createTypedRule({
5504
+ create(context) {
5505
+ const tsExtrasImports = collectDirectNamedValueImportsFromSource(context.sourceCode, TS_EXTRAS_MODULE_SOURCE);
5506
+ return {
5507
+ 'CallExpression[callee.type="MemberExpression"][callee.property.type="Identifier"][callee.property.name="filter"]'(node) {
5508
+ const callbackMatch = getSingleParameterExpressionArrowFilterCallback(node);
5509
+ if (!callbackMatch) {
5510
+ return;
5511
+ }
5512
+ const { callback, parameter } = callbackMatch;
5513
+ const propName = extractPropertyDefinedGuardBody(context, callback.body, parameter.name);
5514
+ if (propName === null) {
5515
+ return;
5516
+ }
5517
+ reportWithOptionalFix({
5518
+ context,
5519
+ fix: createSafeValueNodeTextReplacementFix({
5520
+ context,
5521
+ importedName: "isPropertyDefined",
5522
+ imports: tsExtrasImports,
5523
+ replacementTextFactory: (localName) => `${localName}(${JSON.stringify(propName)})`,
5524
+ reportFixIntent: "autofix",
5525
+ sourceModuleName: TS_EXTRAS_MODULE_SOURCE,
5526
+ targetNode: callback
5527
+ }),
5528
+ messageId: "preferTsExtrasIsPropertyDefined",
5529
+ node: callback
5530
+ });
5531
+ }
5532
+ };
5533
+ },
5534
+ meta: {
5535
+ deprecated: false,
5536
+ docs: {
5537
+ description: "require ts-extras isPropertyDefined in Array.filter callbacks instead of inline property-undefined checks.",
5538
+ frozen: false,
5539
+ recommended: true,
5540
+ requiresTypeChecking: false,
5541
+ typefestConfigs: [
5542
+ "typefest.configs.minimal",
5543
+ "typefest.configs.recommended",
5544
+ "typefest.configs.strict",
5545
+ "typefest.configs.all",
5546
+ "typefest.configs.ts-extras/type-guards"
5547
+ ],
5548
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-ts-extras-is-property-defined"
5549
+ },
5550
+ fixable: "code",
5551
+ messages: {
5552
+ preferTsExtrasIsPropertyDefined: "Prefer `isPropertyDefined` from `ts-extras` over an inline property-undefined filter callback."
5553
+ },
5554
+ schema: [],
5555
+ type: "suggestion"
5556
+ },
5557
+ name: "prefer-ts-extras-is-property-defined"
5558
+ });
5559
+ var prefer_ts_extras_is_property_defined_default = preferTsExtrasIsPropertyDefinedRule;
5560
+
5561
+ // dist/rules/prefer-ts-extras-is-property-present.js
5562
+ var extractPropertyPresentGuardBody = (body, paramName) => {
5563
+ if (body.type !== "BinaryExpression" || body.operator !== "!=") {
5564
+ return null;
5565
+ }
5566
+ const { left, right } = body;
5567
+ if (left.type === "MemberExpression" && !left.computed && left.object.type === "Identifier" && left.object.name === paramName && left.property.type === "Identifier" && right.type === "Literal" && right.value === null) {
5568
+ return left.property.name;
5569
+ }
5570
+ if (right.type === "MemberExpression" && !right.computed && right.object.type === "Identifier" && right.object.name === paramName && right.property.type === "Identifier" && left.type === "Literal" && left.value === null) {
5571
+ return right.property.name;
5572
+ }
5573
+ return null;
5574
+ };
5575
+ var preferTsExtrasIsPropertyPresentRule = createTypedRule({
5576
+ create(context) {
5577
+ const tsExtrasImports = collectDirectNamedValueImportsFromSource(context.sourceCode, TS_EXTRAS_MODULE_SOURCE);
5578
+ return {
5579
+ 'CallExpression[callee.type="MemberExpression"][callee.property.type="Identifier"][callee.property.name="filter"]'(node) {
5580
+ const callbackMatch = getSingleParameterExpressionArrowFilterCallback(node);
5581
+ if (!callbackMatch) {
5582
+ return;
5583
+ }
5584
+ const { callback, parameter } = callbackMatch;
5585
+ const propName = extractPropertyPresentGuardBody(callback.body, parameter.name);
5586
+ if (propName === null) {
5587
+ return;
5588
+ }
5589
+ reportWithOptionalFix({
5590
+ context,
5591
+ fix: createSafeValueNodeTextReplacementFix({
5592
+ context,
5593
+ importedName: "isPropertyPresent",
5594
+ imports: tsExtrasImports,
5595
+ replacementTextFactory: (localName) => `${localName}(${JSON.stringify(propName)})`,
5596
+ reportFixIntent: "autofix",
5597
+ sourceModuleName: TS_EXTRAS_MODULE_SOURCE,
5598
+ targetNode: callback
5599
+ }),
5600
+ messageId: "preferTsExtrasIsPropertyPresent",
5601
+ node: callback
5602
+ });
5603
+ }
5604
+ };
5605
+ },
5606
+ meta: {
5607
+ deprecated: false,
5608
+ docs: {
5609
+ description: "require ts-extras isPropertyPresent in Array.filter callbacks instead of inline property-nullish checks.",
5610
+ frozen: false,
5611
+ recommended: true,
5612
+ requiresTypeChecking: false,
5613
+ typefestConfigs: [
5614
+ "typefest.configs.minimal",
5615
+ "typefest.configs.recommended",
5616
+ "typefest.configs.strict",
5617
+ "typefest.configs.all",
5618
+ "typefest.configs.ts-extras/type-guards"
5619
+ ],
5620
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-ts-extras-is-property-present"
5621
+ },
5622
+ fixable: "code",
5623
+ messages: {
5624
+ preferTsExtrasIsPropertyPresent: "Prefer `isPropertyPresent` from `ts-extras` over an inline property-nullish filter callback."
5625
+ },
5626
+ schema: [],
5627
+ type: "suggestion"
5628
+ },
5629
+ name: "prefer-ts-extras-is-property-present"
5630
+ });
5631
+ var prefer_ts_extras_is_property_present_default = preferTsExtrasIsPropertyPresentRule;
5632
+
5356
5633
  // dist/rules/prefer-ts-extras-is-safe-integer.js
5357
5634
  var preferTsExtrasIsSafeIntegerRule = createTypedRule({
5358
5635
  create(context) {
@@ -6610,8 +6887,59 @@ var preferTsExtrasStringSplitRule = createTypedRule({
6610
6887
  });
6611
6888
  var prefer_ts_extras_string_split_default = preferTsExtrasStringSplitRule;
6612
6889
 
6613
- // dist/rules/prefer-type-fest-abstract-constructor.js
6890
+ // dist/rules/prefer-type-fest-absolute.js
6614
6891
  var import_ts_extras32 = require("ts-extras");
6892
+ var ABSOLUTE_ALIAS_NAMES = /* @__PURE__ */ new Set([
6893
+ "Abs",
6894
+ "AbsoluteValue"
6895
+ ]);
6896
+ var preferTypeFestAbsoluteRule = createTypedRule({
6897
+ create(context) {
6898
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
6899
+ return {
6900
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
6901
+ if (node.typeName.type !== "Identifier" || !(0, import_ts_extras32.setHas)(ABSOLUTE_ALIAS_NAMES, node.typeName.name)) {
6902
+ return;
6903
+ }
6904
+ const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, "Absolute", typeFestDirectImports);
6905
+ reportWithOptionalFix({
6906
+ context,
6907
+ data: { aliasName: node.typeName.name },
6908
+ fix: aliasReplacementFix,
6909
+ messageId: "preferAbsolute",
6910
+ node
6911
+ });
6912
+ }
6913
+ };
6914
+ },
6915
+ meta: {
6916
+ deprecated: false,
6917
+ docs: {
6918
+ description: "require TypeFest `Absolute` over common `Abs` or `AbsoluteValue` aliases.",
6919
+ frozen: false,
6920
+ recommended: true,
6921
+ requiresTypeChecking: false,
6922
+ typefestConfigs: [
6923
+ "typefest.configs.recommended",
6924
+ "typefest.configs.strict",
6925
+ "typefest.configs.all",
6926
+ "typefest.configs.type-fest/types"
6927
+ ],
6928
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-absolute"
6929
+ },
6930
+ fixable: "code",
6931
+ messages: {
6932
+ preferAbsolute: "Prefer `Absolute` from type-fest over `{{aliasName}}`."
6933
+ },
6934
+ schema: [],
6935
+ type: "suggestion"
6936
+ },
6937
+ name: "prefer-type-fest-absolute"
6938
+ });
6939
+ var prefer_type_fest_absolute_default = preferTypeFestAbsoluteRule;
6940
+
6941
+ // dist/rules/prefer-type-fest-abstract-constructor.js
6942
+ var import_ts_extras33 = require("ts-extras");
6615
6943
  var preferTypeFestAbstractConstructorRule = createTypedRule({
6616
6944
  create(context) {
6617
6945
  const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
@@ -6621,7 +6949,7 @@ var preferTypeFestAbstractConstructorRule = createTypedRule({
6621
6949
  if (!node.abstract) {
6622
6950
  return;
6623
6951
  }
6624
- const replacementFix = !(0, import_ts_extras32.isDefined)(node.typeParameters) && (0, import_ts_extras32.isDefined)(node.returnType) ? createSafeTypeNodeTextReplacementFix(node, "AbstractConstructor", `AbstractConstructor<${sourceCode.getText(node.returnType.typeAnnotation)}, [${(0, import_ts_extras32.arrayJoin)(node.params.map((parameter) => sourceCode.getText(parameter)), ", ")}]>`, typeFestDirectImports) : null;
6952
+ const replacementFix = !(0, import_ts_extras33.isDefined)(node.typeParameters) && (0, import_ts_extras33.isDefined)(node.returnType) ? createSafeTypeNodeTextReplacementFix(node, "AbstractConstructor", `AbstractConstructor<${sourceCode.getText(node.returnType.typeAnnotation)}, [${(0, import_ts_extras33.arrayJoin)(node.params.map((parameter) => sourceCode.getText(parameter)), ", ")}]>`, typeFestDirectImports) : null;
6625
6953
  reportWithOptionalFix({
6626
6954
  context,
6627
6955
  fix: replacementFix,
@@ -7308,7 +7636,7 @@ var preferTypeFestConditionalPickRule = createTypedRule({
7308
7636
  var prefer_type_fest_conditional_pick_default = preferTypeFestConditionalPickRule;
7309
7637
 
7310
7638
  // dist/rules/prefer-type-fest-constructor.js
7311
- var import_ts_extras33 = require("ts-extras");
7639
+ var import_ts_extras34 = require("ts-extras");
7312
7640
  var preferTypeFestConstructorRule = createTypedRule({
7313
7641
  create(context) {
7314
7642
  const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
@@ -7318,7 +7646,7 @@ var preferTypeFestConstructorRule = createTypedRule({
7318
7646
  if (node.abstract) {
7319
7647
  return;
7320
7648
  }
7321
- 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;
7649
+ const replacementFix = !(0, import_ts_extras34.isDefined)(node.typeParameters) && (0, import_ts_extras34.isDefined)(node.returnType) ? createSafeTypeNodeTextReplacementFix(node, "Constructor", `Constructor<${sourceCode.getText(node.returnType.typeAnnotation)}, [${(0, import_ts_extras34.arrayJoin)(node.params.map((parameter) => sourceCode.getText(parameter)), ", ")}]>`, typeFestDirectImports) : null;
7322
7650
  reportWithOptionalFix({
7323
7651
  context,
7324
7652
  fix: replacementFix,
@@ -7939,14 +8267,14 @@ var preferTypeFestJsonPrimitiveRule = createTypedRule({
7939
8267
  var prefer_type_fest_json_primitive_default = preferTypeFestJsonPrimitiveRule;
7940
8268
 
7941
8269
  // dist/rules/prefer-type-fest-json-value.js
7942
- var import_ts_extras34 = require("ts-extras");
8270
+ var import_ts_extras35 = require("ts-extras");
7943
8271
  var isStringLikeKeyType = (node) => node.type === "TSStringKeyword" || node.type === "TSLiteralType" && node.literal.type === "Literal" && node.literal.value === "string";
7944
8272
  var isRecordLikeUnknownOrAny = (typeNode) => {
7945
8273
  if (typeNode.typeName.type !== "Identifier" || typeNode.typeName.name !== "Record" || typeNode.typeArguments?.params.length !== 2) {
7946
8274
  return false;
7947
8275
  }
7948
8276
  const [keyType, valueType] = typeNode.typeArguments.params;
7949
- return (0, import_ts_extras34.isDefined)(keyType) && (0, import_ts_extras34.isDefined)(valueType) && isStringLikeKeyType(keyType) && (valueType.type === "TSUnknownKeyword" || valueType.type === "TSAnyKeyword");
8277
+ return (0, import_ts_extras35.isDefined)(keyType) && (0, import_ts_extras35.isDefined)(valueType) && isStringLikeKeyType(keyType) && (valueType.type === "TSUnknownKeyword" || valueType.type === "TSAnyKeyword");
7950
8278
  };
7951
8279
  var preferTypeFestJsonValueRule = createTypedRule({
7952
8280
  create(context) {
@@ -8296,7 +8624,7 @@ var preferTypeFestLessThanRule = createTypedRule({
8296
8624
  var prefer_type_fest_less_than_default = preferTypeFestLessThanRule;
8297
8625
 
8298
8626
  // dist/rules/prefer-type-fest-literal-union.js
8299
- var import_ts_extras35 = require("ts-extras");
8627
+ var import_ts_extras36 = require("ts-extras");
8300
8628
  var literalUnionFamilies = [
8301
8629
  "bigint",
8302
8630
  "boolean",
@@ -8323,7 +8651,7 @@ var isLiteralMemberForFamily = (node, family) => {
8323
8651
  if (typeof node.literal.value === "bigint") {
8324
8652
  return true;
8325
8653
  }
8326
- const literalWithPotentialBigInt = (0, import_ts_extras35.safeCastTo)(node.literal);
8654
+ const literalWithPotentialBigInt = (0, import_ts_extras36.safeCastTo)(node.literal);
8327
8655
  return typeof literalWithPotentialBigInt.bigint === "string";
8328
8656
  }
8329
8657
  if (family === "boolean") {
@@ -8362,7 +8690,7 @@ var getLiteralUnionReplacementText = (sourceCode, node, family) => {
8362
8690
  if (literalMembers.length === 0) {
8363
8691
  return null;
8364
8692
  }
8365
- const literalText = literalMembers.length === 1 ? sourceCode.getText((0, import_ts_extras35.arrayFirst)(literalMembers)) : (0, import_ts_extras35.arrayJoin)(literalMembers.map((member) => sourceCode.getText(member)), " | ");
8693
+ const literalText = literalMembers.length === 1 ? sourceCode.getText((0, import_ts_extras36.arrayFirst)(literalMembers)) : (0, import_ts_extras36.arrayJoin)(literalMembers.map((member) => sourceCode.getText(member)), " | ");
8366
8694
  return `LiteralUnion<${literalText}, ${family}>`;
8367
8695
  };
8368
8696
  var preferTypeFestLiteralUnionRule = createTypedRule({
@@ -8628,6 +8956,51 @@ var preferTypeFestNonEmptyTupleRule = createTypedRule({
8628
8956
  });
8629
8957
  var prefer_type_fest_non_empty_tuple_default = preferTypeFestNonEmptyTupleRule;
8630
8958
 
8959
+ // dist/rules/prefer-type-fest-non-nullable-deep.js
8960
+ var preferTypeFestNonNullableDeepRule = createTypedRule({
8961
+ create(context) {
8962
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
8963
+ return {
8964
+ 'TSTypeReference[typeName.type="Identifier"]'(node) {
8965
+ if (node.typeName.type !== "Identifier" || node.typeName.name !== "DeepNonNullable") {
8966
+ return;
8967
+ }
8968
+ const aliasReplacementFix = createSafeTypeReferenceReplacementFix(node, "NonNullableDeep", typeFestDirectImports);
8969
+ reportWithOptionalFix({
8970
+ context,
8971
+ fix: aliasReplacementFix,
8972
+ messageId: "preferNonNullableDeep",
8973
+ node
8974
+ });
8975
+ }
8976
+ };
8977
+ },
8978
+ meta: {
8979
+ deprecated: false,
8980
+ docs: {
8981
+ description: "require TypeFest `NonNullableDeep` over `DeepNonNullable` aliases.",
8982
+ frozen: false,
8983
+ recommended: true,
8984
+ requiresTypeChecking: false,
8985
+ typefestConfigs: [
8986
+ "typefest.configs.recommended",
8987
+ "typefest.configs.strict",
8988
+ "typefest.configs.all",
8989
+ "typefest.configs.type-fest/types"
8990
+ ],
8991
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-non-nullable-deep"
8992
+ },
8993
+ fixable: "code",
8994
+ messages: {
8995
+ preferNonNullableDeep: "Prefer `NonNullableDeep` from type-fest over `DeepNonNullable`."
8996
+ },
8997
+ schema: [],
8998
+ type: "suggestion"
8999
+ },
9000
+ name: "prefer-type-fest-non-nullable-deep"
9001
+ });
9002
+ var prefer_type_fest_non_nullable_deep_default = preferTypeFestNonNullableDeepRule;
9003
+
8631
9004
  // dist/rules/prefer-type-fest-omit-index-signature.js
8632
9005
  var omitIndexSignatureAliasReplacements = {
8633
9006
  RemoveIndexSignature: "OmitIndexSignature"
@@ -8686,7 +9059,7 @@ var preferTypeFestOmitIndexSignatureRule = createTypedRule({
8686
9059
  var prefer_type_fest_omit_index_signature_default = preferTypeFestOmitIndexSignatureRule;
8687
9060
 
8688
9061
  // dist/rules/prefer-type-fest-optional.js
8689
- var import_ts_extras36 = require("ts-extras");
9062
+ var import_ts_extras37 = require("ts-extras");
8690
9063
  var OPTIONAL_TYPE_NAME = "Optional";
8691
9064
  var EXCLUDE_TYPE_NAME = "Exclude";
8692
9065
  var NON_NULLABLE_TYPE_NAME = "NonNullable";
@@ -8740,8 +9113,8 @@ var preferTypeFestOptionalRule = createTypedRule({
8740
9113
  if (node.types.length !== 2) {
8741
9114
  return;
8742
9115
  }
8743
- const firstMember = (0, import_ts_extras36.arrayFirst)(node.types);
8744
- const secondMember = (0, import_ts_extras36.arrayAt)(node.types, 1);
9116
+ const firstMember = (0, import_ts_extras37.arrayFirst)(node.types);
9117
+ const secondMember = (0, import_ts_extras37.arrayAt)(node.types, 1);
8745
9118
  if (!firstMember || !secondMember) {
8746
9119
  return;
8747
9120
  }
@@ -8915,16 +9288,16 @@ var preferTypeFestPartialDeepRule = createTypedRule({
8915
9288
  var prefer_type_fest_partial_deep_default = preferTypeFestPartialDeepRule;
8916
9289
 
8917
9290
  // dist/rules/prefer-type-fest-pick-index-signature.js
8918
- var import_ts_extras37 = require("ts-extras");
9291
+ var import_ts_extras38 = require("ts-extras");
8919
9292
  var isEmptyObjectTypeLiteral = (node) => node.type === "TSTypeLiteral" && node.members.length === 0;
8920
9293
  var hasPickIndexSignatureMappedTypeShape = (node) => {
8921
9294
  if (node.key.type !== "Identifier") {
8922
9295
  return false;
8923
9296
  }
8924
- if (node.readonly !== false && (0, import_ts_extras37.isDefined)(node.readonly)) {
9297
+ if (node.readonly !== false && (0, import_ts_extras38.isDefined)(node.readonly)) {
8925
9298
  return false;
8926
9299
  }
8927
- if (node.optional !== false && (0, import_ts_extras37.isDefined)(node.optional)) {
9300
+ if (node.optional !== false && (0, import_ts_extras38.isDefined)(node.optional)) {
8928
9301
  return false;
8929
9302
  }
8930
9303
  const constraint = node.constraint;
@@ -9062,7 +9435,7 @@ var preferTypeFestPrimitiveRule = createTypedRule({
9062
9435
  var prefer_type_fest_primitive_default = preferTypeFestPrimitiveRule;
9063
9436
 
9064
9437
  // dist/rules/prefer-type-fest-promisable.js
9065
- var import_ts_extras38 = require("ts-extras");
9438
+ var import_ts_extras39 = require("ts-extras");
9066
9439
  var PROMISABLE_TYPE_NAME = "Promisable";
9067
9440
  var PROMISE_TYPE_NAME = "Promise";
9068
9441
  var promisableAliasReplacements = {
@@ -9078,10 +9451,10 @@ var getPromiseInnerType = (node) => {
9078
9451
  return null;
9079
9452
  }
9080
9453
  const typeArguments = node.typeArguments?.params;
9081
- if (!(0, import_ts_extras38.isDefined)(typeArguments)) {
9454
+ if (!(0, import_ts_extras39.isDefined)(typeArguments)) {
9082
9455
  return null;
9083
9456
  }
9084
- return (0, import_ts_extras38.arrayFirst)(typeArguments) ?? null;
9457
+ return (0, import_ts_extras39.arrayFirst)(typeArguments) ?? null;
9085
9458
  };
9086
9459
  var preferTypeFestPromisableRule = createTypedRule({
9087
9460
  create(context, [options] = defaultOptions3) {
@@ -9934,12 +10307,12 @@ var preferTypeFestSimplifyRule = createTypedRule({
9934
10307
  var prefer_type_fest_simplify_default = preferTypeFestSimplifyRule;
9935
10308
 
9936
10309
  // dist/rules/prefer-type-fest-stringified.js
9937
- var import_ts_extras39 = require("ts-extras");
10310
+ var import_ts_extras40 = require("ts-extras");
9938
10311
  var hasStringifiedMappedTypeShape = (node) => {
9939
- if (node.readonly !== false && (0, import_ts_extras39.isDefined)(node.readonly)) {
10312
+ if (node.readonly !== false && (0, import_ts_extras40.isDefined)(node.readonly)) {
9940
10313
  return false;
9941
10314
  }
9942
- if (node.optional !== false && (0, import_ts_extras39.isDefined)(node.optional)) {
10315
+ if (node.optional !== false && (0, import_ts_extras40.isDefined)(node.optional)) {
9943
10316
  return false;
9944
10317
  }
9945
10318
  if (node.nameType !== null) {
@@ -10233,8 +10606,64 @@ var preferTypeFestTupleOfRule = createTypedRule({
10233
10606
  });
10234
10607
  var prefer_type_fest_tuple_of_default = preferTypeFestTupleOfRule;
10235
10608
 
10609
+ // dist/rules/prefer-type-fest-union-length.js
10610
+ var import_ts_extras41 = require("ts-extras");
10611
+ var preferTypeFestUnionLengthRule = createTypedRule({
10612
+ create(context) {
10613
+ const typeFestDirectImports = collectDirectNamedImportsFromSource(context.sourceCode, TYPE_FEST_MODULE_SOURCE);
10614
+ return {
10615
+ TSIndexedAccessType(node) {
10616
+ const { indexType, objectType } = node;
10617
+ if (objectType.type !== "TSTypeReference" || objectType.typeName.type !== "Identifier" || objectType.typeName.name !== "UnionToTuple") {
10618
+ return;
10619
+ }
10620
+ if (indexType.type !== "TSLiteralType" || indexType.literal.type !== "Literal" || indexType.literal.value !== "length") {
10621
+ return;
10622
+ }
10623
+ const typeParams = objectType.typeArguments?.params;
10624
+ if (typeParams?.length !== 1) {
10625
+ return;
10626
+ }
10627
+ const typeArgText = context.sourceCode.getText((0, import_ts_extras41.arrayFirst)(typeParams));
10628
+ const replacementText = `UnionLength<${typeArgText}>`;
10629
+ const replacementFix = createSafeTypeNodeTextReplacementFix(node, "UnionLength", replacementText, typeFestDirectImports);
10630
+ reportWithOptionalFix({
10631
+ context,
10632
+ fix: replacementFix,
10633
+ messageId: "preferUnionLength",
10634
+ node
10635
+ });
10636
+ }
10637
+ };
10638
+ },
10639
+ meta: {
10640
+ deprecated: false,
10641
+ docs: {
10642
+ description: "require TypeFest `UnionLength` over `UnionToTuple<T>['length']`.",
10643
+ frozen: false,
10644
+ recommended: true,
10645
+ requiresTypeChecking: false,
10646
+ typefestConfigs: [
10647
+ "typefest.configs.recommended",
10648
+ "typefest.configs.strict",
10649
+ "typefest.configs.all",
10650
+ "typefest.configs.type-fest/types"
10651
+ ],
10652
+ url: "https://nick2bad4u.github.io/eslint-plugin-typefest/docs/rules/prefer-type-fest-union-length"
10653
+ },
10654
+ fixable: "code",
10655
+ messages: {
10656
+ preferUnionLength: "Prefer `UnionLength<T>` from type-fest over `UnionToTuple<T>['length']`."
10657
+ },
10658
+ schema: [],
10659
+ type: "suggestion"
10660
+ },
10661
+ name: "prefer-type-fest-union-length"
10662
+ });
10663
+ var prefer_type_fest_union_length_default = preferTypeFestUnionLengthRule;
10664
+
10236
10665
  // dist/rules/prefer-type-fest-union-member.js
10237
- var import_ts_extras40 = require("ts-extras");
10666
+ var import_ts_extras42 = require("ts-extras");
10238
10667
  var UNION_MEMBER_TYPE_NAME = "UnionMember";
10239
10668
  var UNION_TO_INTERSECTION_TYPE_NAME = "UnionToIntersection";
10240
10669
  var IS_NEVER_TYPE_NAME = "IsNever";
@@ -10265,7 +10694,7 @@ var getUnionArgumentTextFromExtractor = ({ node, sourceCode }) => {
10265
10694
  if (!isIdentifierTypeReferenceNamed(node.checkType, UNION_TO_INTERSECTION_TYPE_NAME)) {
10266
10695
  return null;
10267
10696
  }
10268
- const extractorArgument = (0, import_ts_extras40.arrayFirst)(node.checkType.typeArguments?.params ?? []);
10697
+ const extractorArgument = (0, import_ts_extras42.arrayFirst)(node.checkType.typeArguments?.params ?? []);
10269
10698
  if (!extractorArgument) {
10270
10699
  return null;
10271
10700
  }
@@ -10300,7 +10729,7 @@ var getUnionMemberEquivalentArgumentText = ({ node, sourceCode }) => {
10300
10729
  if (!isIdentifierTypeReferenceNamed(node.checkType, IS_NEVER_TYPE_NAME) || !isBooleanLiteralType(node.extendsType, true) || node.trueType.type !== "TSNeverKeyword") {
10301
10730
  return null;
10302
10731
  }
10303
- const guardedArgument = (0, import_ts_extras40.arrayFirst)(node.checkType.typeArguments?.params ?? []);
10732
+ const guardedArgument = (0, import_ts_extras42.arrayFirst)(node.checkType.typeArguments?.params ?? []);
10304
10733
  if (!guardedArgument) {
10305
10734
  return null;
10306
10735
  }
@@ -11034,6 +11463,7 @@ var typefestRuleRegistry = {
11034
11463
  "prefer-ts-extras-as-writable": prefer_ts_extras_as_writable_default,
11035
11464
  "prefer-ts-extras-assert-defined": prefer_ts_extras_assert_defined_default,
11036
11465
  "prefer-ts-extras-assert-error": prefer_ts_extras_assert_error_default,
11466
+ "prefer-ts-extras-assert-never": prefer_ts_extras_assert_never_default,
11037
11467
  "prefer-ts-extras-assert-present": prefer_ts_extras_assert_present_default,
11038
11468
  "prefer-ts-extras-is-defined": prefer_ts_extras_is_defined_default,
11039
11469
  "prefer-ts-extras-is-defined-filter": prefer_ts_extras_is_defined_filter_default,
@@ -11044,6 +11474,8 @@ var typefestRuleRegistry = {
11044
11474
  "prefer-ts-extras-is-integer": prefer_ts_extras_is_integer_default,
11045
11475
  "prefer-ts-extras-is-present": prefer_ts_extras_is_present_default,
11046
11476
  "prefer-ts-extras-is-present-filter": prefer_ts_extras_is_present_filter_default,
11477
+ "prefer-ts-extras-is-property-defined": prefer_ts_extras_is_property_defined_default,
11478
+ "prefer-ts-extras-is-property-present": prefer_ts_extras_is_property_present_default,
11047
11479
  "prefer-ts-extras-is-safe-integer": prefer_ts_extras_is_safe_integer_default,
11048
11480
  "prefer-ts-extras-key-in": prefer_ts_extras_key_in_default,
11049
11481
  "prefer-ts-extras-not": prefer_ts_extras_not_default,
@@ -11057,6 +11489,7 @@ var typefestRuleRegistry = {
11057
11489
  "prefer-ts-extras-safe-cast-to": prefer_ts_extras_safe_cast_to_default,
11058
11490
  "prefer-ts-extras-set-has": prefer_ts_extras_set_has_default,
11059
11491
  "prefer-ts-extras-string-split": prefer_ts_extras_string_split_default,
11492
+ "prefer-type-fest-absolute": prefer_type_fest_absolute_default,
11060
11493
  "prefer-type-fest-abstract-constructor": prefer_type_fest_abstract_constructor_default,
11061
11494
  "prefer-type-fest-and-all": prefer_type_fest_and_all_default,
11062
11495
  "prefer-type-fest-array-length": prefer_type_fest_array_length_default,
@@ -11084,6 +11517,7 @@ var typefestRuleRegistry = {
11084
11517
  "prefer-type-fest-merge": prefer_type_fest_merge_default,
11085
11518
  "prefer-type-fest-merge-exclusive": prefer_type_fest_merge_exclusive_default,
11086
11519
  "prefer-type-fest-non-empty-tuple": prefer_type_fest_non_empty_tuple_default,
11520
+ "prefer-type-fest-non-nullable-deep": prefer_type_fest_non_nullable_deep_default,
11087
11521
  "prefer-type-fest-omit-index-signature": prefer_type_fest_omit_index_signature_default,
11088
11522
  "prefer-type-fest-optional": prefer_type_fest_optional_default,
11089
11523
  "prefer-type-fest-or-all": prefer_type_fest_or_all_default,
@@ -11107,6 +11541,7 @@ var typefestRuleRegistry = {
11107
11541
  "prefer-type-fest-stringified": prefer_type_fest_stringified_default,
11108
11542
  "prefer-type-fest-tagged-brands": prefer_type_fest_tagged_brands_default,
11109
11543
  "prefer-type-fest-tuple-of": prefer_type_fest_tuple_of_default,
11544
+ "prefer-type-fest-union-length": prefer_type_fest_union_length_default,
11110
11545
  "prefer-type-fest-union-member": prefer_type_fest_union_member_default,
11111
11546
  "prefer-type-fest-union-to-intersection": prefer_type_fest_union_to_intersection_default,
11112
11547
  "prefer-type-fest-union-to-tuple": prefer_type_fest_union_to_tuple_default,
@@ -11131,7 +11566,7 @@ function getPackageVersion(pkg) {
11131
11566
  const version = Reflect.get(pkg, "version");
11132
11567
  return typeof version === "string" ? version : "0.0.0";
11133
11568
  }
11134
- var packageJsonValue = (0, import_ts_extras41.safeCastTo)(package_default);
11569
+ var packageJsonValue = (0, import_ts_extras43.safeCastTo)(package_default);
11135
11570
  var typeScriptParserValue = import_parser3.default;
11136
11571
  var defaultParserOptions = {
11137
11572
  ecmaVersion: "latest",
@@ -11139,10 +11574,10 @@ var defaultParserOptions = {
11139
11574
  };
11140
11575
  var normalizeParserOptions = (parserOptions) => parserOptions !== null && typeof parserOptions === "object" && !Array.isArray(parserOptions) ? { ...parserOptions } : { ...defaultParserOptions };
11141
11576
  var typefestEslintRules = typefestRules;
11142
- var isTypefestRuleName = (value) => (0, import_ts_extras41.objectHasIn)(typefestRules, value);
11577
+ var isTypefestRuleName = (value) => (0, import_ts_extras43.objectHasIn)(typefestRules, value);
11143
11578
  var typefestRuleEntries = (() => {
11144
11579
  const entries = [];
11145
- for (const [ruleName] of (0, import_ts_extras41.objectEntries)(typefestRules)) {
11580
+ for (const [ruleName] of (0, import_ts_extras43.objectEntries)(typefestRules)) {
11146
11581
  if (!isTypefestRuleName(ruleName)) {
11147
11582
  continue;
11148
11583
  }
@@ -11169,7 +11604,7 @@ var derivePresetRuleNamesByConfig = () => {
11169
11604
  const presetRuleNamesByConfig2 = createEmptyPresetRuleMap();
11170
11605
  for (const [ruleName] of typefestRuleEntries) {
11171
11606
  const configNames = rulePresetMembership[ruleName];
11172
- if (!(0, import_ts_extras41.isDefined)(configNames) || (0, import_ts_extras41.isEmpty)(configNames)) {
11607
+ if (!(0, import_ts_extras43.isDefined)(configNames) || (0, import_ts_extras43.isEmpty)(configNames)) {
11173
11608
  throw new TypeError(`Rule '${ruleName}' is missing preset membership metadata.`);
11174
11609
  }
11175
11610
  for (const configName of configNames) {
@@ -11197,7 +11632,7 @@ function errorRulesFor(ruleNames) {
11197
11632
  var presetRuleNamesByConfig = derivePresetRuleNamesByConfig();
11198
11633
  var recommendedRuleNames = [];
11199
11634
  for (const ruleName of presetRuleNamesByConfig.recommended) {
11200
- if ((0, import_ts_extras41.setHas)(typeCheckedRuleNames, ruleName)) {
11635
+ if ((0, import_ts_extras43.setHas)(typeCheckedRuleNames, ruleName)) {
11201
11636
  continue;
11202
11637
  }
11203
11638
  recommendedRuleNames.push(ruleName);
@@ -11219,7 +11654,7 @@ function withTypefestPlugin(config, plugin, options) {
11219
11654
  const existingLanguageOptions = config.languageOptions ?? {};
11220
11655
  const existingParserOptions = existingLanguageOptions["parserOptions"];
11221
11656
  const parserOptions = normalizeParserOptions(existingParserOptions);
11222
- if (options.requiresTypeChecking && !(0, import_ts_extras41.objectHasIn)(parserOptions, "projectService")) {
11657
+ if (options.requiresTypeChecking && !(0, import_ts_extras43.objectHasIn)(parserOptions, "projectService")) {
11223
11658
  Reflect.set(parserOptions, "projectService", true);
11224
11659
  }
11225
11660
  const languageOptions = {