@typescript-eslint/eslint-plugin 8.31.2-alpha.8 → 8.32.1-alpha.0

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 (41) hide show
  1. package/dist/rules/await-thenable.js +2 -2
  2. package/dist/rules/enum-utils/shared.js +1 -1
  3. package/dist/rules/no-confusing-void-expression.js +3 -3
  4. package/dist/rules/no-floating-promises.d.ts.map +1 -1
  5. package/dist/rules/no-floating-promises.js +15 -27
  6. package/dist/rules/no-meaningless-void-operator.js +1 -1
  7. package/dist/rules/no-misused-promises.js +8 -8
  8. package/dist/rules/no-misused-spread.js +2 -2
  9. package/dist/rules/no-redundant-type-constituents.js +1 -1
  10. package/dist/rules/no-unnecessary-condition.js +5 -5
  11. package/dist/rules/no-unnecessary-template-expression.js +1 -1
  12. package/dist/rules/no-unnecessary-type-assertion.js +2 -2
  13. package/dist/rules/no-unnecessary-type-conversion.d.ts.map +1 -1
  14. package/dist/rules/no-unnecessary-type-conversion.js +4 -2
  15. package/dist/rules/no-unsafe-enum-comparison.js +4 -4
  16. package/dist/rules/no-unsafe-unary-minus.js +1 -1
  17. package/dist/rules/non-nullable-type-assertion-style.js +1 -1
  18. package/dist/rules/only-throw-error.d.ts +1 -0
  19. package/dist/rules/only-throw-error.d.ts.map +1 -1
  20. package/dist/rules/only-throw-error.js +47 -0
  21. package/dist/rules/prefer-find.js +2 -2
  22. package/dist/rules/prefer-nullish-coalescing.js +2 -2
  23. package/dist/rules/prefer-optional-chain-utils/analyzeChain.js +1 -1
  24. package/dist/rules/prefer-optional-chain-utils/checkNullishAndReport.js +1 -1
  25. package/dist/rules/prefer-optional-chain-utils/gatherLogicalOperands.js +1 -1
  26. package/dist/rules/prefer-reduce-type-parameter.js +2 -2
  27. package/dist/rules/prefer-regexp-exec.js +1 -1
  28. package/dist/rules/restrict-plus-operands.js +4 -4
  29. package/dist/rules/strict-boolean-expressions.d.ts.map +1 -1
  30. package/dist/rules/strict-boolean-expressions.js +3 -3
  31. package/dist/rules/switch-exhaustiveness-check.js +4 -4
  32. package/dist/rules/unbound-method.d.ts.map +1 -1
  33. package/dist/rules/unbound-method.js +2 -2
  34. package/dist/rules/use-unknown-in-catch-callback-variable.js +1 -1
  35. package/dist/util/isArrayMethodCallWithPredicate.js +2 -2
  36. package/dist/util/promiseUtils.d.ts +28 -0
  37. package/dist/util/promiseUtils.d.ts.map +1 -0
  38. package/dist/util/promiseUtils.js +98 -0
  39. package/dist/util/truthinessUtils.js +4 -4
  40. package/docs/rules/only-throw-error.mdx +6 -0
  41. package/package.json +15 -17
@@ -87,7 +87,7 @@ exports.default = (0, util_1.createRule)({
87
87
  return;
88
88
  }
89
89
  const hasAsyncIteratorSymbol = tsutils
90
- .unionTypeParts(type)
90
+ .unionConstituents(type)
91
91
  .some(typePart => tsutils.getWellKnownSymbolPropertyOfType(typePart, 'asyncIterator', checker) != null);
92
92
  if (!hasAsyncIteratorSymbol) {
93
93
  context.report({
@@ -118,7 +118,7 @@ exports.default = (0, util_1.createRule)({
118
118
  continue;
119
119
  }
120
120
  const hasAsyncDisposeSymbol = tsutils
121
- .unionTypeParts(type)
121
+ .unionConstituents(type)
122
122
  .some(typePart => tsutils.getWellKnownSymbolPropertyOfType(typePart, 'asyncDispose', checker) != null);
123
123
  if (!hasAsyncDisposeSymbol) {
124
124
  context.report({
@@ -66,7 +66,7 @@ function getBaseEnumType(typeChecker, type) {
66
66
  */
67
67
  function getEnumLiterals(type) {
68
68
  return tsutils
69
- .unionTypeParts(type)
69
+ .unionConstituents(type)
70
70
  .filter((subType) => (0, util_1.isTypeFlagSet)(subType, ts.TypeFlags.EnumLiteral));
71
71
  }
72
72
  /**
@@ -327,7 +327,7 @@ exports.default = (0, util_1.createRule)({
327
327
  return callSignatures.some(signature => {
328
328
  const returnType = signature.getReturnType();
329
329
  return tsutils
330
- .unionTypeParts(returnType)
330
+ .unionConstituents(returnType)
331
331
  .some(tsutils.isIntrinsicVoidType);
332
332
  });
333
333
  }
@@ -342,14 +342,14 @@ exports.default = (0, util_1.createRule)({
342
342
  if (functionTSNode.type) {
343
343
  const returnType = checker.getTypeFromTypeNode(functionTSNode.type);
344
344
  return tsutils
345
- .unionTypeParts(returnType)
345
+ .unionConstituents(returnType)
346
346
  .some(tsutils.isIntrinsicVoidType);
347
347
  }
348
348
  if (ts.isExpression(functionTSNode)) {
349
349
  const functionType = checker.getContextualType(functionTSNode);
350
350
  if (functionType) {
351
351
  return tsutils
352
- .unionTypeParts(functionType)
352
+ .unionConstituents(functionType)
353
353
  .some(isFunctionReturnTypeIncludesVoid);
354
354
  }
355
355
  }
@@ -1 +1 @@
1
- {"version":3,"file":"no-floating-promises.d.ts","sourceRoot":"","sources":["../../src/rules/no-floating-promises.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAMnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAepD,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,sBAAsB,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAChD,yBAAyB,CAAC,EAAE,oBAAoB,EAAE,CAAC;QACnD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB;CACF,CAAC;AAEF,MAAM,MAAM,SAAS,GACjB,UAAU,GACV,kBAAkB,GAClB,iBAAiB,GACjB,sBAAsB,GACtB,0BAA0B,GAC1B,iCAAiC,GACjC,qCAAqC,GACrC,cAAc,CAAC;;AAmBnB,wBAkaG"}
1
+ {"version":3,"file":"no-floating-promises.d.ts","sourceRoot":"","sources":["../../src/rules/no-floating-promises.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAMnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAmBpD,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,sBAAsB,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAChD,yBAAyB,CAAC,EAAE,oBAAoB,EAAE,CAAC;QACnD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB;CACF,CAAC;AAEF,MAAM,MAAM,SAAS,GACjB,UAAU,GACV,kBAAkB,GAClB,iBAAiB,GACjB,sBAAsB,GACtB,0BAA0B,GAC1B,iCAAiC,GACjC,qCAAqC,GACrC,cAAc,CAAC;;AAmBnB,wBAqZG"}
@@ -37,6 +37,7 @@ const utils_1 = require("@typescript-eslint/utils");
37
37
  const tsutils = __importStar(require("ts-api-utils"));
38
38
  const ts = __importStar(require("typescript"));
39
39
  const util_1 = require("../util");
40
+ const promiseUtils_1 = require("../util/promiseUtils");
40
41
  const messageBase = 'Promises must be awaited, end with a call to .catch, or end with a call to .then with a rejection handler.';
41
42
  const messageBaseVoid = 'Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler' +
42
43
  ' or be explicitly marked as ignored with the `void` operator.';
@@ -256,33 +257,20 @@ exports.default = (0, util_1.createRule)({
256
257
  if (node.type === utils_1.AST_NODE_TYPES.CallExpression) {
257
258
  // If the outer expression is a call, a `.catch()` or `.then()` with
258
259
  // rejection handler handles the promise.
259
- const { callee } = node;
260
- if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
261
- const methodName = (0, util_1.getStaticMemberAccessValue)(callee, context);
262
- const catchRejectionHandler = methodName === 'catch' && node.arguments.length >= 1
263
- ? node.arguments[0]
264
- : undefined;
265
- if (catchRejectionHandler) {
266
- if (isValidRejectionHandler(catchRejectionHandler)) {
260
+ const promiseHandlingMethodCall = (0, promiseUtils_1.parseCatchCall)(node, context) ?? (0, promiseUtils_1.parseThenCall)(node, context);
261
+ if (promiseHandlingMethodCall != null) {
262
+ const onRejected = promiseHandlingMethodCall.onRejected;
263
+ if (onRejected != null) {
264
+ if (isValidRejectionHandler(onRejected)) {
267
265
  return { isUnhandled: false };
268
266
  }
269
267
  return { isUnhandled: true, nonFunctionHandler: true };
270
268
  }
271
- const thenRejectionHandler = methodName === 'then' && node.arguments.length >= 2
272
- ? node.arguments[1]
273
- : undefined;
274
- if (thenRejectionHandler) {
275
- if (isValidRejectionHandler(thenRejectionHandler)) {
276
- return { isUnhandled: false };
277
- }
278
- return { isUnhandled: true, nonFunctionHandler: true };
279
- }
280
- // `x.finally()` is transparent to resolution of the promise, so check `x`.
281
- // ("object" in this context is the `x` in `x.finally()`)
282
- const promiseFinallyObject = methodName === 'finally' ? callee.object : undefined;
283
- if (promiseFinallyObject) {
284
- return isUnhandledPromise(checker, promiseFinallyObject);
285
- }
269
+ return { isUnhandled: true };
270
+ }
271
+ const promiseFinallyCall = (0, promiseUtils_1.parseFinallyCall)(node, context);
272
+ if (promiseFinallyCall != null) {
273
+ return isUnhandledPromise(checker, promiseFinallyCall.object);
286
274
  }
287
275
  // All other cases are unhandled.
288
276
  return { isUnhandled: true };
@@ -309,7 +297,7 @@ exports.default = (0, util_1.createRule)({
309
297
  function isPromiseArray(node) {
310
298
  const type = checker.getTypeAtLocation(node);
311
299
  for (const ty of tsutils
312
- .unionTypeParts(type)
300
+ .unionConstituents(type)
313
301
  .map(t => checker.getApparentType(t))) {
314
302
  if (checker.isArrayType(ty)) {
315
303
  const arrayType = checker.getTypeArguments(ty)[0];
@@ -334,7 +322,7 @@ exports.default = (0, util_1.createRule)({
334
322
  return false;
335
323
  }
336
324
  // Otherwise, we always consider the built-in Promise to be Promise-like...
337
- const typeParts = tsutils.unionTypeParts(checker.getApparentType(type));
325
+ const typeParts = tsutils.unionConstituents(checker.getApparentType(type));
338
326
  if (typeParts.some(typePart => (0, util_1.isBuiltinSymbolLike)(services.program, typePart, 'Promise'))) {
339
327
  return true;
340
328
  }
@@ -363,7 +351,7 @@ exports.default = (0, util_1.createRule)({
363
351
  },
364
352
  });
365
353
  function hasMatchingSignature(type, matcher) {
366
- for (const t of tsutils.unionTypeParts(type)) {
354
+ for (const t of tsutils.unionConstituents(type)) {
367
355
  if (t.getCallSignatures().some(matcher)) {
368
356
  return true;
369
357
  }
@@ -372,7 +360,7 @@ function hasMatchingSignature(type, matcher) {
372
360
  }
373
361
  function isFunctionParam(checker, param, node) {
374
362
  const type = checker.getApparentType(checker.getTypeOfSymbolAtLocation(param, node));
375
- for (const t of tsutils.unionTypeParts(type)) {
363
+ for (const t of tsutils.unionConstituents(type)) {
376
364
  if (t.getCallSignatures().length !== 0) {
377
365
  return true;
378
366
  }
@@ -79,7 +79,7 @@ exports.default = (0, util_1.createRule)({
79
79
  ]);
80
80
  };
81
81
  const argType = services.getTypeAtLocation(node.argument);
82
- const unionParts = tsutils.unionTypeParts(argType);
82
+ const unionParts = tsutils.unionConstituents(argType);
83
83
  if (unionParts.every(part => part.flags & (ts.TypeFlags.Void | ts.TypeFlags.Undefined))) {
84
84
  context.report({
85
85
  node,
@@ -551,7 +551,7 @@ exports.default = (0, util_1.createRule)({
551
551
  });
552
552
  function isSometimesThenable(checker, node) {
553
553
  const type = checker.getTypeAtLocation(node);
554
- for (const subType of tsutils.unionTypeParts(checker.getApparentType(type))) {
554
+ for (const subType of tsutils.unionConstituents(checker.getApparentType(type))) {
555
555
  if (tsutils.isThenableType(checker, node, subType)) {
556
556
  return true;
557
557
  }
@@ -564,7 +564,7 @@ function isSometimesThenable(checker, node) {
564
564
  // branches is thenable.
565
565
  function isAlwaysThenable(checker, node) {
566
566
  const type = checker.getTypeAtLocation(node);
567
- for (const subType of tsutils.unionTypeParts(checker.getApparentType(type))) {
567
+ for (const subType of tsutils.unionConstituents(checker.getApparentType(type))) {
568
568
  const thenProp = subType.getProperty('then');
569
569
  // If one of the alternates has no then property, it is not thenable in all
570
570
  // cases.
@@ -576,7 +576,7 @@ function isAlwaysThenable(checker, node) {
576
576
  // be of the right form to consider it thenable.
577
577
  const thenType = checker.getTypeOfSymbolAtLocation(thenProp, node);
578
578
  let hasThenableSignature = false;
579
- for (const subType of tsutils.unionTypeParts(thenType)) {
579
+ for (const subType of tsutils.unionConstituents(thenType)) {
580
580
  for (const signature of subType.getCallSignatures()) {
581
581
  if (signature.parameters.length !== 0 &&
582
582
  isFunctionParam(checker, signature.parameters[0], node)) {
@@ -602,7 +602,7 @@ function isAlwaysThenable(checker, node) {
602
602
  }
603
603
  function isFunctionParam(checker, param, node) {
604
604
  const type = checker.getApparentType(checker.getTypeOfSymbolAtLocation(param, node));
605
- for (const subType of tsutils.unionTypeParts(type)) {
605
+ for (const subType of tsutils.unionConstituents(type)) {
606
606
  if (subType.getCallSignatures().length !== 0) {
607
607
  return true;
608
608
  }
@@ -641,7 +641,7 @@ function voidFunctionArguments(checker, node) {
641
641
  const type = checker.getTypeAtLocation(node.expression);
642
642
  // We can't use checker.getResolvedSignature because it prefers an early '() => void' over a later '() => Promise<void>'
643
643
  // See https://github.com/microsoft/TypeScript/issues/48077
644
- for (const subType of tsutils.unionTypeParts(type)) {
644
+ for (const subType of tsutils.unionConstituents(type)) {
645
645
  // Standard function calls and `new` have two different types of signatures
646
646
  const signatures = ts.isCallExpression(node)
647
647
  ? subType.getCallSignatures()
@@ -698,7 +698,7 @@ function anySignatureIsThenableType(checker, node, type) {
698
698
  * @returns Whether type is a thenable-returning function.
699
699
  */
700
700
  function isThenableReturningFunctionType(checker, node, type) {
701
- for (const subType of tsutils.unionTypeParts(type)) {
701
+ for (const subType of tsutils.unionConstituents(type)) {
702
702
  if (anySignatureIsThenableType(checker, node, subType)) {
703
703
  return true;
704
704
  }
@@ -710,7 +710,7 @@ function isThenableReturningFunctionType(checker, node, type) {
710
710
  */
711
711
  function isVoidReturningFunctionType(checker, node, type) {
712
712
  let hadVoidReturn = false;
713
- for (const subType of tsutils.unionTypeParts(type)) {
713
+ for (const subType of tsutils.unionConstituents(type)) {
714
714
  for (const signature of subType.getCallSignatures()) {
715
715
  const returnType = signature.getReturnType();
716
716
  // If a certain positional argument accepts both thenable and void returns,
@@ -729,7 +729,7 @@ function isVoidReturningFunctionType(checker, node, type) {
729
729
  function returnsThenable(checker, node) {
730
730
  const type = checker.getApparentType(checker.getTypeAtLocation(node));
731
731
  return tsutils
732
- .unionTypeParts(type)
732
+ .unionConstituents(type)
733
733
  .some(t => anySignatureIsThenableType(checker, node, t));
734
734
  }
735
735
  function getHeritageTypes(checker, tsNode) {
@@ -97,7 +97,7 @@ exports.default = (0, util_1.createRule)({
97
97
  }
98
98
  }
99
99
  function getMapSpreadSuggestions(node, type) {
100
- const types = tsutils.unionTypeParts(type);
100
+ const types = tsutils.unionConstituents(type);
101
101
  if (types.some(t => !isMap(services.program, t))) {
102
102
  return null;
103
103
  }
@@ -208,7 +208,7 @@ exports.default = (0, util_1.createRule)({
208
208
  });
209
209
  function isIterable(type, checker) {
210
210
  return tsutils
211
- .typeParts(type)
211
+ .typeConstituents(type)
212
212
  .some(t => !!tsutils.getWellKnownSymbolPropertyOfType(t, 'iterator', checker));
213
213
  }
214
214
  function isArray(checker, type) {
@@ -168,7 +168,7 @@ function unionTypePartsUnlessBoolean(type) {
168
168
  tsutils.isFalseLiteralType(type.types[0]) &&
169
169
  tsutils.isTrueLiteralType(type.types[1])
170
170
  ? [type]
171
- : tsutils.unionTypeParts(type);
171
+ : tsutils.unionConstituents(type);
172
172
  }
173
173
  exports.default = (0, util_1.createRule)({
174
174
  name: 'no-redundant-type-constituents',
@@ -44,14 +44,14 @@ function isNullishType(type) {
44
44
  return tsutils.isTypeFlagSet(type, nullishFlag);
45
45
  }
46
46
  function isAlwaysNullish(type) {
47
- return tsutils.unionTypeParts(type).every(isNullishType);
47
+ return tsutils.unionConstituents(type).every(isNullishType);
48
48
  }
49
49
  /**
50
50
  * Note that this differs from {@link isNullableType} in that it doesn't consider
51
51
  * `any` or `unknown` to be nullable.
52
52
  */
53
53
  function isPossiblyNullish(type) {
54
- return tsutils.unionTypeParts(type).some(isNullishType);
54
+ return tsutils.unionConstituents(type).some(isNullishType);
55
55
  }
56
56
  function toStaticValue(type) {
57
57
  // type.isLiteral() only covers numbers/bigints and strings, hence the rest of the branches.
@@ -198,13 +198,13 @@ exports.default = (0, util_1.createRule)({
198
198
  function nodeIsArrayType(node) {
199
199
  const nodeType = (0, util_1.getConstrainedTypeAtLocation)(services, node);
200
200
  return tsutils
201
- .unionTypeParts(nodeType)
201
+ .unionConstituents(nodeType)
202
202
  .some(part => checker.isArrayType(part));
203
203
  }
204
204
  function nodeIsTupleType(node) {
205
205
  const nodeType = (0, util_1.getConstrainedTypeAtLocation)(services, node);
206
206
  return tsutils
207
- .unionTypeParts(nodeType)
207
+ .unionConstituents(nodeType)
208
208
  .some(part => checker.isTupleType(part));
209
209
  }
210
210
  function isArrayIndexExpression(node) {
@@ -223,7 +223,7 @@ exports.default = (0, util_1.createRule)({
223
223
  // `any` or `unknown` or a naked type variable
224
224
  function isConditionalAlwaysNecessary(type) {
225
225
  return tsutils
226
- .unionTypeParts(type)
226
+ .unionConstituents(type)
227
227
  .some(part => (0, util_1.isTypeAnyType)(part) ||
228
228
  (0, util_1.isTypeUnknownType)(part) ||
229
229
  (0, util_1.isTypeFlagSet)(part, ts.TypeFlags.TypeVariable));
@@ -77,7 +77,7 @@ exports.default = (0, util_1.createRule)({
77
77
  return isStringLike(type);
78
78
  }
79
79
  function isEnumMemberType(type) {
80
- return tsutils.typeParts(type).some(t => {
80
+ return tsutils.typeConstituents(type).some(t => {
81
81
  const symbol = t.getSymbol();
82
82
  return !!(symbol?.valueDeclaration && ts.isEnumMember(symbol.valueDeclaration));
83
83
  });
@@ -171,10 +171,10 @@ exports.default = (0, util_1.createRule)({
171
171
  (0, util_1.isTypeFlagSet)(cast, ts.TypeFlags.Undefined) &&
172
172
  tsutils.isCompilerOptionEnabled(compilerOptions, 'exactOptionalPropertyTypes')) {
173
173
  const uncastParts = tsutils
174
- .unionTypeParts(uncast)
174
+ .unionConstituents(uncast)
175
175
  .filter(part => !(0, util_1.isTypeFlagSet)(part, ts.TypeFlags.Undefined));
176
176
  const castParts = tsutils
177
- .unionTypeParts(cast)
177
+ .unionConstituents(cast)
178
178
  .filter(part => !(0, util_1.isTypeFlagSet)(part, ts.TypeFlags.Undefined));
179
179
  if (uncastParts.length !== castParts.length) {
180
180
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"no-unnecessary-type-conversion.d.ts","sourceRoot":"","sources":["../../src/rules/no-unnecessary-type-conversion.ts"],"names":[],"mappings":"AAgBA,KAAK,UAAU,GACX,eAAe,GACf,kBAAkB,GAClB,2BAA2B,CAAC;;AAEhC,wBAoVG"}
1
+ {"version":3,"file":"no-unnecessary-type-conversion.d.ts","sourceRoot":"","sources":["../../src/rules/no-unnecessary-type-conversion.ts"],"names":[],"mappings":"AAgBA,KAAK,UAAU,GACX,eAAe,GACf,kBAAkB,GAClB,2BAA2B,CAAC;;AAEhC,wBAsVG"}
@@ -34,7 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const utils_1 = require("@typescript-eslint/utils");
37
- const ts_api_utils_1 = require("ts-api-utils");
37
+ const tsutils = __importStar(require("ts-api-utils"));
38
38
  const ts = __importStar(require("typescript"));
39
39
  const util_1 = require("../util");
40
40
  exports.default = (0, util_1.createRule)({
@@ -57,7 +57,9 @@ exports.default = (0, util_1.createRule)({
57
57
  defaultOptions: [],
58
58
  create(context) {
59
59
  function doesUnderlyingTypeMatchFlag(type, typeFlag) {
60
- return (0, ts_api_utils_1.unionTypeParts)(type).every(t => (0, util_1.isTypeFlagSet)(t, typeFlag));
60
+ return tsutils
61
+ .unionConstituents(type)
62
+ .every(t => (0, util_1.isTypeFlagSet)(t, typeFlag));
61
63
  }
62
64
  const services = (0, util_1.getParserServices)(context);
63
65
  function handleUnaryOperator(node, typeFlag, typeString, violation, isDoubleOperator) {
@@ -46,13 +46,13 @@ function typeViolates(leftTypeParts, rightType) {
46
46
  (leftEnumValueTypes.has(ts.TypeFlags.String) && isStringLike(rightType)));
47
47
  }
48
48
  function isNumberLike(type) {
49
- const typeParts = tsutils.intersectionTypeParts(type);
49
+ const typeParts = tsutils.intersectionConstituents(type);
50
50
  return typeParts.some(typePart => {
51
51
  return tsutils.isTypeFlagSet(typePart, ts.TypeFlags.Number | ts.TypeFlags.NumberLike);
52
52
  });
53
53
  }
54
54
  function isStringLike(type) {
55
- const typeParts = tsutils.intersectionTypeParts(type);
55
+ const typeParts = tsutils.intersectionConstituents(type);
56
56
  return typeParts.some(typePart => {
57
57
  return tsutils.isTypeFlagSet(typePart, ts.TypeFlags.String | ts.TypeFlags.StringLike);
58
58
  });
@@ -116,8 +116,8 @@ exports.default = (0, util_1.createRule)({
116
116
  // declare const something: Fruit | Vegetable;
117
117
  // something === Fruit.Apple;
118
118
  // ```
119
- const leftTypeParts = tsutils.unionTypeParts(leftType);
120
- const rightTypeParts = tsutils.unionTypeParts(rightType);
119
+ const leftTypeParts = tsutils.unionConstituents(leftType);
120
+ const rightTypeParts = tsutils.unionConstituents(rightType);
121
121
  // If a type exists in both sides, we consider this comparison safe:
122
122
  //
123
123
  // ```ts
@@ -61,7 +61,7 @@ exports.default = util.createRule({
61
61
  const argType = util.getConstrainedTypeAtLocation(services, node.argument);
62
62
  const checker = services.program.getTypeChecker();
63
63
  if (tsutils
64
- .unionTypeParts(argType)
64
+ .unionConstituents(argType)
65
65
  .some(type => !tsutils.isTypeFlagSet(type, ts.TypeFlags.Any |
66
66
  ts.TypeFlags.Never |
67
67
  ts.TypeFlags.BigIntLike |
@@ -60,7 +60,7 @@ exports.default = (0, util_1.createRule)({
60
60
  if (tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) {
61
61
  return undefined;
62
62
  }
63
- return tsutils.unionTypeParts(type);
63
+ return tsutils.unionConstituents(type);
64
64
  };
65
65
  const couldBeNullish = (type) => {
66
66
  if (type.flags & ts.TypeFlags.TypeParameter) {
@@ -3,6 +3,7 @@ export type MessageIds = 'object' | 'undef';
3
3
  export type Options = [
4
4
  {
5
5
  allow?: TypeOrValueSpecifier[];
6
+ allowRethrowing?: boolean;
6
7
  allowThrowingAny?: boolean;
7
8
  allowThrowingUnknown?: boolean;
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"only-throw-error.d.ts","sourceRoot":"","sources":["../../src/rules/only-throw-error.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAYpD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC;CACF,CAAC;;AAEF,wBAuFG"}
1
+ {"version":3,"file":"only-throw-error.d.ts","sourceRoot":"","sources":["../../src/rules/only-throw-error.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAepD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC;CACF,CAAC;;AAEF,wBA4JG"}
@@ -34,8 +34,10 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const utils_1 = require("@typescript-eslint/utils");
37
+ const ts_api_utils_1 = require("ts-api-utils");
37
38
  const ts = __importStar(require("typescript"));
38
39
  const util_1 = require("../util");
40
+ const promiseUtils_1 = require("../util/promiseUtils");
39
41
  exports.default = (0, util_1.createRule)({
40
42
  name: 'only-throw-error',
41
43
  meta: {
@@ -59,6 +61,10 @@ exports.default = (0, util_1.createRule)({
59
61
  ...util_1.typeOrValueSpecifiersSchema,
60
62
  description: 'Type specifiers that can be thrown.',
61
63
  },
64
+ allowRethrowing: {
65
+ type: 'boolean',
66
+ description: 'Whether to allow rethrowing caught values that are not `Error` objects.',
67
+ },
62
68
  allowThrowingAny: {
63
69
  type: 'boolean',
64
70
  description: 'Whether to always allow throwing values typed as `any`.',
@@ -74,6 +80,7 @@ exports.default = (0, util_1.createRule)({
74
80
  defaultOptions: [
75
81
  {
76
82
  allow: [],
83
+ allowRethrowing: true,
77
84
  allowThrowingAny: true,
78
85
  allowThrowingUnknown: true,
79
86
  },
@@ -81,11 +88,51 @@ exports.default = (0, util_1.createRule)({
81
88
  create(context, [options]) {
82
89
  const services = (0, util_1.getParserServices)(context);
83
90
  const allow = options.allow;
91
+ function isRethrownError(node) {
92
+ if (node.type !== utils_1.AST_NODE_TYPES.Identifier) {
93
+ return false;
94
+ }
95
+ const scope = context.sourceCode.getScope(node);
96
+ const smVariable = (0, util_1.nullThrows)((0, util_1.findVariable)(scope, node), `Variable ${node.name} should exist in scope manager`);
97
+ const variableDefinitions = smVariable.defs.filter(def => def.isVariableDefinition);
98
+ if (variableDefinitions.length !== 1) {
99
+ return false;
100
+ }
101
+ const def = smVariable.defs[0];
102
+ // try { /* ... */ } catch (x) { throw x; }
103
+ if (def.node.type === utils_1.AST_NODE_TYPES.CatchClause) {
104
+ return true;
105
+ }
106
+ // promise.catch(x => { throw x; })
107
+ // promise.then(onFulfilled, x => { throw x; })
108
+ if (def.node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
109
+ def.node.params.length >= 1 &&
110
+ def.node.params[0] === def.name &&
111
+ def.node.parent.type === utils_1.AST_NODE_TYPES.CallExpression) {
112
+ const callExpression = def.node.parent;
113
+ const parsedPromiseHandlingCall = (0, promiseUtils_1.parseCatchCall)(callExpression, context) ??
114
+ (0, promiseUtils_1.parseThenCall)(callExpression, context);
115
+ if (parsedPromiseHandlingCall != null) {
116
+ const { object, onRejected } = parsedPromiseHandlingCall;
117
+ if (onRejected === def.node) {
118
+ const tsObjectNode = services.esTreeNodeToTSNodeMap.get(object);
119
+ // make sure we're actually dealing with a promise
120
+ if ((0, ts_api_utils_1.isThenableType)(services.program.getTypeChecker(), tsObjectNode)) {
121
+ return true;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ return false;
127
+ }
84
128
  function checkThrowArgument(node) {
85
129
  if (node.type === utils_1.AST_NODE_TYPES.AwaitExpression ||
86
130
  node.type === utils_1.AST_NODE_TYPES.YieldExpression) {
87
131
  return;
88
132
  }
133
+ if (options.allowRethrowing && isRethrownError(node)) {
134
+ return;
135
+ }
89
136
  const type = services.getTypeAtLocation(node);
90
137
  if ((0, util_1.typeMatchesSomeSpecifier)(type, allow, services.program)) {
91
138
  return;
@@ -109,7 +109,7 @@ exports.default = (0, util_1.createRule)({
109
109
  */
110
110
  function isArrayish(type) {
111
111
  let isAtLeastOneArrayishComponent = false;
112
- for (const unionPart of tsutils.unionTypeParts(type)) {
112
+ for (const unionPart of tsutils.unionConstituents(type)) {
113
113
  if (tsutils.isIntrinsicNullType(unionPart) ||
114
114
  tsutils.isIntrinsicUndefinedType(unionPart)) {
115
115
  continue;
@@ -117,7 +117,7 @@ exports.default = (0, util_1.createRule)({
117
117
  // apparently checker.isArrayType(T[] & S[]) => false.
118
118
  // so we need to check the intersection parts individually.
119
119
  const isArrayOrIntersectionThereof = tsutils
120
- .intersectionTypeParts(unionPart)
120
+ .intersectionConstituents(unionPart)
121
121
  .every(intersectionPart => checker.isArrayType(intersectionPart) ||
122
122
  checker.isTupleType(intersectionPart));
123
123
  if (!isArrayOrIntersectionThereof) {
@@ -195,9 +195,9 @@ exports.default = (0, util_1.createRule)({
195
195
  return false;
196
196
  }
197
197
  if (tsutils
198
- .typeParts(type)
198
+ .typeConstituents(type)
199
199
  .some(t => tsutils
200
- .intersectionTypeParts(t)
200
+ .intersectionConstituents(t)
201
201
  .some(t => tsutils.isTypeFlagSet(t, ignorableFlags)))) {
202
202
  return false;
203
203
  }
@@ -43,7 +43,7 @@ const compareNodes_1 = require("./compareNodes");
43
43
  const gatherLogicalOperands_1 = require("./gatherLogicalOperands");
44
44
  function includesType(parserServices, node, typeFlagIn) {
45
45
  const typeFlag = typeFlagIn | ts.TypeFlags.Any | ts.TypeFlags.Unknown;
46
- const types = (0, ts_api_utils_1.unionTypeParts)(parserServices.getTypeAtLocation(node));
46
+ const types = (0, ts_api_utils_1.unionConstituents)(parserServices.getTypeAtLocation(node));
47
47
  for (const type of types) {
48
48
  if ((0, util_1.isTypeFlagSet)(type, typeFlag)) {
49
49
  return true;
@@ -39,7 +39,7 @@ const ts_api_utils_1 = require("ts-api-utils");
39
39
  const ts = __importStar(require("typescript"));
40
40
  function checkNullishAndReport(context, parserServices, { requireNullish }, maybeNullishNodes, descriptor) {
41
41
  if (!requireNullish ||
42
- maybeNullishNodes.some(node => (0, ts_api_utils_1.unionTypeParts)(parserServices.getTypeAtLocation(node)).some(t => (0, type_utils_1.isTypeFlagSet)(t, ts.TypeFlags.Null | ts.TypeFlags.Undefined)))) {
42
+ maybeNullishNodes.some(node => (0, ts_api_utils_1.unionConstituents)(parserServices.getTypeAtLocation(node)).some(t => (0, type_utils_1.isTypeFlagSet)(t, ts.TypeFlags.Null | ts.TypeFlags.Undefined)))) {
43
43
  context.report(descriptor);
44
44
  }
45
45
  }
@@ -72,7 +72,7 @@ var NullishComparisonType;
72
72
  const NULLISH_FLAGS = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
73
73
  function isValidFalseBooleanCheckType(node, disallowFalseyLiteral, parserServices, options) {
74
74
  const type = parserServices.getTypeAtLocation(node);
75
- const types = (0, ts_api_utils_1.unionTypeParts)(type);
75
+ const types = (0, ts_api_utils_1.unionConstituents)(type);
76
76
  if (disallowFalseyLiteral &&
77
77
  /*
78
78
  ```
@@ -56,9 +56,9 @@ exports.default = (0, util_1.createRule)({
56
56
  const checker = services.program.getTypeChecker();
57
57
  function isArrayType(type) {
58
58
  return tsutils
59
- .unionTypeParts(type)
59
+ .unionConstituents(type)
60
60
  .every(unionPart => tsutils
61
- .intersectionTypeParts(unionPart)
61
+ .intersectionConstituents(unionPart)
62
62
  .every(t => checker.isArrayType(t) || checker.isTupleType(t)));
63
63
  }
64
64
  return {
@@ -147,7 +147,7 @@ exports.default = (0, util_1.createRule)({
147
147
  });
148
148
  }
149
149
  const argumentType = services.getTypeAtLocation(argumentNode);
150
- const argumentTypes = collectArgumentTypes(tsutils.unionTypeParts(argumentType));
150
+ const argumentTypes = collectArgumentTypes(tsutils.unionConstituents(argumentType));
151
151
  switch (argumentTypes) {
152
152
  case ArgumentType.RegExp:
153
153
  return context.report({
@@ -156,7 +156,7 @@ exports.default = (0, util_1.createRule)({
156
156
  continue;
157
157
  }
158
158
  // RegExps also contain ts.TypeFlags.Any & ts.TypeFlags.Object
159
- for (const subBaseType of tsutils.unionTypeParts(baseType)) {
159
+ for (const subBaseType of tsutils.unionConstituents(baseType)) {
160
160
  const typeName = (0, util_1.getTypeName)(typeChecker, subBaseType);
161
161
  if (typeName === 'RegExp'
162
162
  ? !allowRegExp ||
@@ -221,11 +221,11 @@ exports.default = (0, util_1.createRule)({
221
221
  });
222
222
  function isDeeplyObjectType(type) {
223
223
  return type.isIntersection()
224
- ? tsutils.intersectionTypeParts(type).every(tsutils.isObjectType)
225
- : tsutils.unionTypeParts(type).every(tsutils.isObjectType);
224
+ ? tsutils.intersectionConstituents(type).every(tsutils.isObjectType)
225
+ : tsutils.unionConstituents(type).every(tsutils.isObjectType);
226
226
  }
227
227
  function isTypeFlagSetInUnion(type, flag) {
228
228
  return tsutils
229
- .unionTypeParts(type)
229
+ .unionConstituents(type)
230
230
  .some(subType => tsutils.isTypeFlagSet(subType, flag));
231
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"strict-boolean-expressions.d.ts","sourceRoot":"","sources":["../../src/rules/strict-boolean-expressions.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,sDAAsD,CAAC,EAAE,OAAO,CAAC;QACjE,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB;CACF,CAAC;AAEF,KAAK,uBAAuB,GACxB,mBAAmB,GACnB,+BAA+B,GAC/B,4BAA4B,GAC5B,8BAA8B,GAC9B,8BAA8B,GAC9B,8BAA8B,GAC9B,uBAAuB,GACvB,sBAAsB,GACtB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,CAAC;AAE3B,MAAM,MAAM,SAAS,GACjB,yBAAyB,GACzB,uCAAuC,GACvC,oCAAoC,GACpC,gCAAgC,GAChC,0BAA0B,GAC1B,wBAAwB,GACxB,4BAA4B,GAC5B,iCAAiC,GACjC,yBAAyB,GACzB,yBAAyB,GACzB,gCAAgC,GAChC,0BAA0B,GAC1B,yBAAyB,GACzB,2BAA2B,GAC3B,mBAAmB,GACnB,wBAAwB,GACxB,uBAAuB,CAAC;;AAE5B,wBAm/BG"}
1
+ {"version":3,"file":"strict-boolean-expressions.d.ts","sourceRoot":"","sources":["../../src/rules/strict-boolean-expressions.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,sDAAsD,CAAC,EAAE,OAAO,CAAC;QACjE,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB;CACF,CAAC;AAEF,KAAK,uBAAuB,GACxB,mBAAmB,GACnB,+BAA+B,GAC/B,4BAA4B,GAC5B,8BAA8B,GAC9B,8BAA8B,GAC9B,8BAA8B,GAC9B,uBAAuB,GACvB,sBAAsB,GACtB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,CAAC;AAE3B,MAAM,MAAM,SAAS,GACjB,yBAAyB,GACzB,uCAAuC,GACvC,oCAAoC,GACpC,gCAAgC,GAChC,0BAA0B,GAC1B,wBAAwB,GACxB,4BAA4B,GAC5B,iCAAiC,GACjC,yBAAyB,GACzB,yBAAyB,GACzB,gCAAgC,GAChC,0BAA0B,GAC1B,yBAAyB,GACzB,2BAA2B,GAC3B,mBAAmB,GACnB,wBAAwB,GACxB,uBAAuB,CAAC;;AAE5B,wBAq/BG"}
@@ -237,7 +237,7 @@ exports.default = (0, util_1.createRule)({
237
237
  return type;
238
238
  });
239
239
  const flattenTypes = [
240
- ...new Set(returnTypes.flatMap(type => tsutils.unionTypeParts(type))),
240
+ ...new Set(returnTypes.flatMap(type => tsutils.unionConstituents(type))),
241
241
  ];
242
242
  const types = inspectVariantTypes(flattenTypes);
243
243
  const reportType = determineReportType(types);
@@ -774,7 +774,7 @@ exports.default = (0, util_1.createRule)({
774
774
  */
775
775
  function checkNode(node) {
776
776
  const type = (0, util_1.getConstrainedTypeAtLocation)(services, node);
777
- const types = inspectVariantTypes(tsutils.unionTypeParts(type));
777
+ const types = inspectVariantTypes(tsutils.unionConstituents(type));
778
778
  const reportType = determineReportType(types);
779
779
  if (reportType != null) {
780
780
  context.report({
@@ -799,7 +799,7 @@ exports.default = (0, util_1.createRule)({
799
799
  // If incoming type is either "true" or "false", there will be one type
800
800
  // object with intrinsicName set accordingly
801
801
  // If incoming type is boolean, there will be two type objects with
802
- // intrinsicName set "true" and "false" each because of ts-api-utils.unionTypeParts()
802
+ // intrinsicName set "true" and "false" each because of ts-api-utils.unionConstituents()
803
803
  if (booleans.length === 1) {
804
804
  variantTypes.add(tsutils.isTrueLiteralType(booleans[0]) ? 'truthy boolean' : 'boolean');
805
805
  }
@@ -122,8 +122,8 @@ exports.default = (0, util_1.createRule)({
122
122
  caseTypes.add(caseType);
123
123
  }
124
124
  const missingLiteralBranchTypes = [];
125
- for (const unionPart of tsutils.unionTypeParts(discriminantType)) {
126
- for (const intersectionPart of tsutils.intersectionTypeParts(unionPart)) {
125
+ for (const unionPart of tsutils.unionConstituents(discriminantType)) {
126
+ for (const intersectionPart of tsutils.intersectionConstituents(unionPart)) {
127
127
  if (caseTypes.has(intersectionPart) ||
128
128
  !isTypeLiteralLikeType(intersectionPart)) {
129
129
  continue;
@@ -284,8 +284,8 @@ function isTypeLiteralLikeType(type) {
284
284
  */
285
285
  function doesTypeContainNonLiteralType(type) {
286
286
  return tsutils
287
- .unionTypeParts(type)
287
+ .unionConstituents(type)
288
288
  .some(type => tsutils
289
- .intersectionTypeParts(type)
289
+ .intersectionConstituents(type)
290
290
  .every(subType => !isTypeLiteralLikeType(subType)));
291
291
  }
@@ -1 +1 @@
1
- {"version":3,"file":"unbound-method.d.ts","sourceRoot":"","sources":["../../src/rules/unbound-method.ts"],"names":[],"mappings":"AAkBA,UAAU,MAAM;IACd,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC;AAE/B,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,8BAA8B,CAAC;;AAiFpE,wBA0KG"}
1
+ {"version":3,"file":"unbound-method.d.ts","sourceRoot":"","sources":["../../src/rules/unbound-method.ts"],"names":[],"mappings":"AAkBA,UAAU,MAAM;IACd,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC;AAE/B,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,8BAA8B,CAAC;;AAiFpE,wBA4KG"}
@@ -215,8 +215,8 @@ exports.default = (0, util_1.createRule)({
215
215
  }
216
216
  }
217
217
  for (const intersectionPart of tsutils
218
- .unionTypeParts(services.getTypeAtLocation(node))
219
- .flatMap(unionPart => tsutils.intersectionTypeParts(unionPart))) {
218
+ .unionConstituents(services.getTypeAtLocation(node))
219
+ .flatMap(unionPart => tsutils.intersectionConstituents(unionPart))) {
220
220
  const reported = checkIfMethodAndReport(property.key, intersectionPart.getProperty(property.key.name));
221
221
  if (reported) {
222
222
  break;
@@ -63,7 +63,7 @@ exports.default = (0, util_1.createRule)({
63
63
  const { esTreeNodeToTSNodeMap, program } = (0, util_1.getParserServices)(context);
64
64
  const checker = program.getTypeChecker();
65
65
  function isFlaggableHandlerType(type) {
66
- for (const unionPart of tsutils.unionTypeParts(type)) {
66
+ for (const unionPart of tsutils.unionConstituents(type)) {
67
67
  const callSignatures = tsutils.getCallSignaturesOfType(unionPart);
68
68
  if (callSignatures.length === 0) {
69
69
  // Ignore any non-function components to the type. Those are not this rule's problem.
@@ -58,7 +58,7 @@ function isArrayMethodCallWithPredicate(context, services, node) {
58
58
  const checker = services.program.getTypeChecker();
59
59
  const type = (0, type_utils_1.getConstrainedTypeAtLocation)(services, node.callee.object);
60
60
  return tsutils
61
- .unionTypeParts(type)
62
- .flatMap(part => tsutils.intersectionTypeParts(part))
61
+ .unionConstituents(type)
62
+ .flatMap(part => tsutils.intersectionConstituents(part))
63
63
  .some(t => checker.isArrayType(t) || checker.isTupleType(t));
64
64
  }
@@ -0,0 +1,28 @@
1
+ import type { TSESTree } from '@typescript-eslint/utils';
2
+ import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
3
+ /**
4
+ * Parses a syntactically possible `Promise.then()` call. Does not check the
5
+ * type of the callee.
6
+ */
7
+ export declare function parseThenCall(node: TSESTree.CallExpression, context: RuleContext<string, unknown[]>): {
8
+ onFulfilled?: TSESTree.Expression | undefined;
9
+ onRejected?: TSESTree.Expression | undefined;
10
+ object: TSESTree.Expression;
11
+ } | undefined;
12
+ /**
13
+ * Parses a syntactically possible `Promise.catch()` call. Does not check the
14
+ * type of the callee.
15
+ */
16
+ export declare function parseCatchCall(node: TSESTree.CallExpression, context: RuleContext<string, unknown[]>): {
17
+ onRejected?: TSESTree.Expression | undefined;
18
+ object: TSESTree.Expression;
19
+ } | undefined;
20
+ /**
21
+ * Parses a syntactically possible `Promise.finally()` call. Does not check the
22
+ * type of the callee.
23
+ */
24
+ export declare function parseFinallyCall(node: TSESTree.CallExpression, context: RuleContext<string, unknown[]>): {
25
+ object: TSESTree.Expression;
26
+ onFinally?: TSESTree.Expression | undefined;
27
+ } | undefined;
28
+ //# sourceMappingURL=promiseUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promiseUtils.d.ts","sourceRoot":"","sources":["../../src/util/promiseUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAMtE;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,CAAC,cAAc,EAC7B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAErC;IACE,WAAW,CAAC,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9C,UAAU,CAAC,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;IAC7C,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC;CAC7B,GACD,SAAS,CAqCZ;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,cAAc,EAC7B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAErC;IACE,UAAU,CAAC,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;IAC7C,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC;CAC7B,GACD,SAAS,CAuBZ;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,CAAC,cAAc,EAC7B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAErC;IACE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC;IAC5B,SAAS,CAAC,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;CAC7C,GACD,SAAS,CAsBZ"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseThenCall = parseThenCall;
4
+ exports.parseCatchCall = parseCatchCall;
5
+ exports.parseFinallyCall = parseFinallyCall;
6
+ const utils_1 = require("@typescript-eslint/utils");
7
+ const misc_1 = require("./misc");
8
+ /**
9
+ * Parses a syntactically possible `Promise.then()` call. Does not check the
10
+ * type of the callee.
11
+ */
12
+ function parseThenCall(node, context) {
13
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
14
+ const methodName = (0, misc_1.getStaticMemberAccessValue)(node.callee, context);
15
+ if (methodName === 'then') {
16
+ if (node.arguments.length >= 1) {
17
+ if (node.arguments[0].type === utils_1.AST_NODE_TYPES.SpreadElement) {
18
+ return {
19
+ object: node.callee.object,
20
+ };
21
+ }
22
+ if (node.arguments.length >= 2) {
23
+ if (node.arguments[1].type === utils_1.AST_NODE_TYPES.SpreadElement) {
24
+ return {
25
+ object: node.callee.object,
26
+ onFulfilled: node.arguments[0],
27
+ };
28
+ }
29
+ return {
30
+ object: node.callee.object,
31
+ onFulfilled: node.arguments[0],
32
+ onRejected: node.arguments[1],
33
+ };
34
+ }
35
+ return {
36
+ object: node.callee.object,
37
+ onFulfilled: node.arguments[0],
38
+ };
39
+ }
40
+ return {
41
+ object: node.callee.object,
42
+ };
43
+ }
44
+ }
45
+ return undefined;
46
+ }
47
+ /**
48
+ * Parses a syntactically possible `Promise.catch()` call. Does not check the
49
+ * type of the callee.
50
+ */
51
+ function parseCatchCall(node, context) {
52
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
53
+ const methodName = (0, misc_1.getStaticMemberAccessValue)(node.callee, context);
54
+ if (methodName === 'catch') {
55
+ if (node.arguments.length >= 1) {
56
+ if (node.arguments[0].type === utils_1.AST_NODE_TYPES.SpreadElement) {
57
+ return {
58
+ object: node.callee.object,
59
+ };
60
+ }
61
+ return {
62
+ object: node.callee.object,
63
+ onRejected: node.arguments[0],
64
+ };
65
+ }
66
+ return {
67
+ object: node.callee.object,
68
+ };
69
+ }
70
+ }
71
+ return undefined;
72
+ }
73
+ /**
74
+ * Parses a syntactically possible `Promise.finally()` call. Does not check the
75
+ * type of the callee.
76
+ */
77
+ function parseFinallyCall(node, context) {
78
+ if (node.callee.type === utils_1.AST_NODE_TYPES.MemberExpression) {
79
+ const methodName = (0, misc_1.getStaticMemberAccessValue)(node.callee, context);
80
+ if (methodName === 'finally') {
81
+ if (node.arguments.length >= 1) {
82
+ if (node.arguments[0].type === utils_1.AST_NODE_TYPES.SpreadElement) {
83
+ return {
84
+ object: node.callee.object,
85
+ };
86
+ }
87
+ return {
88
+ object: node.callee.object,
89
+ onFinally: node.arguments[0],
90
+ };
91
+ }
92
+ return {
93
+ object: node.callee.object,
94
+ };
95
+ }
96
+ }
97
+ return undefined;
98
+ }
@@ -41,18 +41,18 @@ const getValueOfLiteralType_1 = require("./getValueOfLiteralType");
41
41
  const isTruthyLiteral = (type) => tsutils.isTrueLiteralType(type) ||
42
42
  (type.isLiteral() && !!(0, getValueOfLiteralType_1.getValueOfLiteralType)(type));
43
43
  const isPossiblyFalsy = (type) => tsutils
44
- .unionTypeParts(type)
44
+ .unionConstituents(type)
45
45
  // Intersections like `string & {}` can also be possibly falsy,
46
46
  // requiring us to look into the intersection.
47
- .flatMap(type => tsutils.intersectionTypeParts(type))
47
+ .flatMap(type => tsutils.intersectionConstituents(type))
48
48
  // PossiblyFalsy flag includes literal values, so exclude ones that
49
49
  // are definitely truthy
50
50
  .filter(t => !isTruthyLiteral(t))
51
51
  .some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy));
52
52
  exports.isPossiblyFalsy = isPossiblyFalsy;
53
53
  const isPossiblyTruthy = (type) => tsutils
54
- .unionTypeParts(type)
55
- .map(type => tsutils.intersectionTypeParts(type))
54
+ .unionConstituents(type)
55
+ .map(type => tsutils.intersectionConstituents(type))
56
56
  .some(intersectionParts =>
57
57
  // It is possible to define intersections that are always falsy,
58
58
  // like `"" & { __brand: string }`.
@@ -123,6 +123,11 @@ interface Options {
123
123
  | string
124
124
  )[];
125
125
 
126
+ /**
127
+ * Whether to allow rethrowing caught values that are not `Error` objects.
128
+ */
129
+ allowRethrowing?: boolean;
130
+
126
131
  /**
127
132
  * Whether to always allow throwing values typed as `any`.
128
133
  */
@@ -136,6 +141,7 @@ interface Options {
136
141
 
137
142
  const defaultOptions: Options = {
138
143
  allow: [],
144
+ allowRethrowing: false,
139
145
  allowThrowingAny: true,
140
146
  allowThrowingUnknown: true,
141
147
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.31.2-alpha.8",
3
+ "version": "8.32.1-alpha.0",
4
4
  "description": "TypeScript plugin for ESLint",
5
5
  "files": [
6
6
  "dist",
@@ -50,50 +50,48 @@
50
50
  ],
51
51
  "scripts": {
52
52
  "build": "tsc -b tsconfig.build.json",
53
- "clean": "tsc -b tsconfig.build.json --clean",
54
- "postclean": "rimraf dist && rimraf coverage",
53
+ "clean": "rimraf dist/ coverage/",
55
54
  "format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore",
56
55
  "generate:breaking-changes": "tsx tools/generate-breaking-changes.mts",
57
56
  "generate:configs": "npx nx generate-configs repo",
58
57
  "lint": "npx nx lint",
59
58
  "test": "vitest --run --config=$INIT_CWD/vitest.config.mts",
60
- "test-single": "vitest --run --config=$INIT_CWD/vitest.config.mts",
59
+ "test-single": "vitest --run --config=$INIT_CWD/vitest.config.mts --no-coverage",
61
60
  "check-types": "npx nx typecheck"
62
61
  },
63
62
  "dependencies": {
64
63
  "@eslint-community/regexpp": "^4.10.0",
65
- "@typescript-eslint/scope-manager": "8.31.2-alpha.8",
66
- "@typescript-eslint/type-utils": "8.31.2-alpha.8",
67
- "@typescript-eslint/utils": "8.31.2-alpha.8",
68
- "@typescript-eslint/visitor-keys": "8.31.2-alpha.8",
64
+ "@typescript-eslint/scope-manager": "8.32.1-alpha.0",
65
+ "@typescript-eslint/type-utils": "8.32.1-alpha.0",
66
+ "@typescript-eslint/utils": "8.32.1-alpha.0",
67
+ "@typescript-eslint/visitor-keys": "8.32.1-alpha.0",
69
68
  "graphemer": "^1.4.0",
70
- "ignore": "^5.3.1",
69
+ "ignore": "^7.0.0",
71
70
  "natural-compare": "^1.4.0",
72
- "ts-api-utils": "^2.0.1"
71
+ "ts-api-utils": "^2.1.0"
73
72
  },
74
73
  "devDependencies": {
75
- "@types/marked": "^5.0.2",
76
74
  "@types/mdast": "^4.0.3",
77
75
  "@types/natural-compare": "*",
78
- "@typescript-eslint/rule-schema-to-typescript-types": "8.31.2-alpha.8",
79
- "@typescript-eslint/rule-tester": "8.31.2-alpha.8",
80
- "@vitest/coverage-v8": "^3.1.1",
76
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.32.1-alpha.0",
77
+ "@typescript-eslint/rule-tester": "8.32.1-alpha.0",
78
+ "@vitest/coverage-v8": "^3.1.2",
81
79
  "ajv": "^6.12.6",
82
80
  "cross-fetch": "*",
83
81
  "eslint": "*",
84
82
  "json-schema": "*",
85
83
  "markdown-table": "^3.0.3",
86
- "marked": "^5.1.2",
84
+ "marked": "^15.0.0",
87
85
  "mdast-util-from-markdown": "^2.0.0",
88
86
  "mdast-util-mdx": "^3.0.0",
89
87
  "micromark-extension-mdxjs": "^3.0.0",
90
88
  "prettier": "^3.2.5",
91
89
  "rimraf": "*",
92
- "title-case": "^3.0.3",
90
+ "title-case": "^4.0.0",
93
91
  "tsx": "*",
94
92
  "typescript": "*",
95
93
  "unist-util-visit": "^5.0.0",
96
- "vitest": "^3.1.1"
94
+ "vitest": "^3.1.2"
97
95
  },
98
96
  "peerDependencies": {
99
97
  "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",