From b13954091ef149fdf7ceeda5405cc99aad17359d Mon Sep 17 00:00:00 2001 From: Alexander T Date: Fri, 10 Jan 2020 21:28:55 +0200 Subject: [PATCH] fix(eslint-plugin): handle error classes using generics (#1428) --- .../src/rules/no-throw-literal.ts | 8 ++- .../tests/rules/no-throw-literal.test.ts | 49 ++++++++++++++----- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index 5d6fa1d7677..c8c5bcc1837 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -29,7 +29,11 @@ export default util.createRule({ function isErrorLike(type: ts.Type): boolean { const symbol = type.getSymbol(); - if (symbol?.getName() === 'Error') { + if (!symbol) { + return false; + } + + if (symbol.getName() === 'Error') { const declarations = symbol.getDeclarations() ?? []; for (const declaration of declarations) { const sourceFile = declaration.getSourceFile(); @@ -39,7 +43,7 @@ export default util.createRule({ } } - const baseTypes = type.getBaseTypes() ?? []; + const baseTypes = checker.getBaseTypes(type as ts.InterfaceType); for (const baseType of baseTypes) { if (isErrorLike(baseType)) { return true; 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 359c2abf3c5..451e88262a3 100644 --- a/packages/eslint-plugin/tests/rules/no-throw-literal.test.ts +++ b/packages/eslint-plugin/tests/rules/no-throw-literal.test.ts @@ -14,8 +14,8 @@ const ruleTester = new RuleTester({ ruleTester.run('no-throw-literal', rule, { valid: [ 'throw new Error();', - "throw new Error('error');", - "throw Error('error');", + 'throw new Error("error");', + 'throw Error("error");', ` const e = new Error(); throw e; @@ -65,16 +65,28 @@ throw new CustomError(); `, 'throw foo = new Error();', 'throw 1, 2, new Error();', - "throw 'literal' && new Error();", - "throw new Error() || 'literal'", - "throw foo ? new Error() : 'literal';", - "throw foo ? 'literal' : new Error();", + 'throw "literal" && new Error();', + 'throw new Error() || "literal"', + 'throw foo ? new Error() : "literal";', + 'throw foo ? "literal" : new Error();', 'function* foo() { let index = 0; throw yield index++; }', 'async function foo() { throw await bar; }', ` import { Error } from './missing'; throw Error; `, + ` +class CustomError extends Error {} +throw new CustomError(); + `, + ` +class CustomError extends Error {} +throw new CustomError(); + `, + ` +class CustomError extends Error {} +throw new CustomError(); + `, ], invalid: [ { @@ -86,7 +98,7 @@ throw Error; ], }, { - code: "throw new String('');", + code: 'throw new String("");', errors: [ { messageId: 'object', @@ -94,7 +106,7 @@ throw Error; ], }, { - code: "throw 'error';", + code: 'throw "error";', errors: [ { messageId: 'object', @@ -134,7 +146,7 @@ throw Error; ], }, { - code: "throw 'a' + 'b';", + code: 'throw "a" + "b";', errors: [ { messageId: 'object', @@ -153,7 +165,7 @@ throw a + 'b'; ], }, { - code: "throw foo = 'error';", + code: 'throw foo = "error";', errors: [ { messageId: 'object', @@ -169,7 +181,7 @@ throw a + 'b'; ], }, { - code: "throw 'literal' && 'not an Error';", + code: 'throw "literal" && "not an Error";', errors: [ { messageId: 'object', @@ -177,7 +189,7 @@ throw a + 'b'; ], }, { - code: "throw foo ? 'not an Error' : 'literal';", + code: 'throw foo ? "not an Error" : "literal";', errors: [ { messageId: 'object', @@ -288,5 +300,18 @@ throw new Error(); }, ], }, + { + code: ` +class CustomError extends Foo {} +throw new CustomError(); + `, + errors: [ + { + messageId: 'object', + line: 3, + column: 7, + }, + ], + }, ], });