Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESLint only-throw-error complains on subclasses #31

Open
1 of 2 tasks
unlight opened this issue Oct 6, 2024 · 1 comment
Open
1 of 2 tasks

ESLint only-throw-error complains on subclasses #31

unlight opened this issue Oct 6, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@unlight
Copy link

unlight commented Oct 6, 2024

Guidelines

  • Please search other issues to make sure this bug has not already been reported.

Describe the bug

ESLint rule https://typescript-eslint.io/rules/only-throw-error/ complains about derived classes

const RecipeError = BaseError.subclass('RecipeError', {
  props: { recipeId },
});
throw new RecipeError('Add failed:'); // <--- ESLint plugin: Expected an error object to be thrown

Looks like typescript-eslint plugin thinks that variable is not inherited from Error

image

Steps to reproduce

See 'Describe the bug'

Environment

"@eslint/js": "^9.12.0"
"typescript-eslint": "^8.8.0"

Pull request (optional)

  • I can submit a pull request.
@unlight unlight added the bug Something isn't working label Oct 6, 2024
@ehmicky
Copy link
Owner

ehmicky commented Oct 6, 2024

Hi @unlight,

Thanks for reporting this.

TypeScript ESLint is using a TypeScript parser, which does not recognize modern-errors error classes as inheriting from Error. In particular, the following function returns false: https://github.com/typescript-eslint/typescript-eslint/blob/e4e8f4ea840b7a48adfeb7bc1cb7aa331829634f/packages/type-utils/src/builtinSymbolLikes.ts#L41

The reason is because modern-errors types are not using the typical pattern for inheriting from Error. Instead of doing class MyError extends Error { ... }, it uses an interface.

interface ErrorSubclassCore<
PluginsArg extends Plugins,
ErrorPropsArg extends ErrorProps,
CustomClassArg extends CustomClass,
> {
/**
* Error subclass
*
* @example
* ```js
* throw new InputError('Missing file path.')
* ```
*/
new <
ChildProps extends ErrorProps = ErrorProps,
AggregateErrorsArg extends AggregateErrors = AggregateErrors,
CauseArg extends Cause = Cause,
>(
message: string,
options?: ParentInstanceOptions<
PluginsArg,
ChildProps,
CustomClassArg,
AggregateErrorsArg,
CauseArg
>,
...extra: ParentExtra<CustomClassArg>
): SpecificErrorInstance<
PluginsArg,
MergeErrorProps<ErrorPropsArg, ChildProps>,
CustomClassArg,
AggregateErrorsArg,
CauseArg
>
readonly prototype: InstanceType<
ErrorSubclassCore<PluginsArg, ErrorPropsArg, CustomClassArg>
>

modern-errors initially relied on the more typical pattern for subclassing Error, but it has many issues due to a few TypeScript bugs. I filed bug reports but those bugs are still pending (after a couple of years). The interface code above is a workaround for those issues.

Therefore, until those TypeScript bugs are fixed, there's no real way forward. The only workaround at the moment is to disable this linting rule in your problem, unfortunately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants