diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index ffa8a614e6b..b85e0cc742d 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -28,6 +28,13 @@ export default util.createRule({ const checker = program.getTypeChecker(); function isErrorLike(type: ts.Type): boolean { + if (type.isIntersection()) { + return type.types.some(isErrorLike); + } + if (type.isUnion()) { + return type.types.every(isErrorLike); + } + const symbol = type.getSymbol(); if (!symbol) { return false; diff --git a/packages/eslint-plugin/tests/rules/no-throw-literal.test.ts b/packages/eslint-plugin/tests/rules/no-throw-literal.test.ts index 7d7b95acbb2..09ecadeb629 100644 --- a/packages/eslint-plugin/tests/rules/no-throw-literal.test.ts +++ b/packages/eslint-plugin/tests/rules/no-throw-literal.test.ts @@ -96,6 +96,19 @@ throw new CustomError(); class CustomError extends Error {} throw new CustomError(); `, + ` +function foo() { + throw Object.assign(new Error('message'), { foo: 'bar' }); +} + `, + { + code: ` +const foo: Error | SyntaxError = bar(); +function bar() { + throw foo; +} + `, + }, ], invalid: [ { @@ -352,5 +365,30 @@ function foo(fn: () => Promise) { }, ], }, + { + code: ` +function foo() { + throw Object.assign({ foo: 'foo' }, { bar: 'bar' }); +} + `, + errors: [ + { + messageId: 'object', + }, + ], + }, + { + code: ` +const foo: Error | { bar: string } = bar(); +function bar() { + throw foo; +} + `, + errors: [ + { + messageId: 'object', + }, + ], + }, ], });