-
-
Notifications
You must be signed in to change notification settings - Fork 43
Description
Summary
The allow option for the typescript/only-throw-error rule accepts package specifiers (e.g. { "from": "package", "name": "ErrorLike", "package": "@apollo/client" }), but types from real npm packages never match. Only types declared inside ambient declare module "..." blocks can match. This makes the option ineffective for common use cases like allowing Apollo Client’s ErrorLike to be thrown.
Environment
- Repository: oxc-project/tsgolint
- Rule:
typescript/only-throw-error - Config:
.oxlintrc.jsonwithoxlint --type-aware - Example dependency:
@apollo/client(or any npm package that exports types via normal.d.tsfiles)
Steps to reproduce
- Install oxlint and oxlint-tsgolint, enable type-aware linting.
- In
.oxlintrc.json, configure:
{
"rules": {
"typescript/only-throw-error": [
"error",
{
"allow": [
{
"from": "package",
"name": "ErrorLike",
"package": "@apollo/client"
}
]
}
]
}
}- In a TS file, use Apollo’s
useLazyQueryand throw itserror:
import { useLazyQuery } from '@apollo/client/react';
const [query] = useLazyQuery(SomeDocument);
async function run() {
const { data, error } = await query({});
if (error) {
throw error; // ← typescript-eslint(only-throw-error): Expected an error object to be thrown.
}
}- Run
oxlint --type-aware.
Expected: No report for throw error, because error is typed as ErrorLike from @apollo/client and that type is in allow.
Actual: The rule reports: Expected an error object to be thrown. The package specifier is ignored.
Root cause
In internal/utils/type_matches_specifier.go:
-
Package specifiers are handled by
typeDeclaredInPackageDeclarationFile, which is true only if either:typeDeclaredInDeclareModule(packageName, declarations)is true, ortypeDeclaredInDeclarationFile(packageName, declarationFiles, program)is true.
-
typeDeclaredInDeclarationFile(lines 219–241) is effectively unimplemented:- The logic that would map declaration files to package names is commented out with a
TODO(port)(“there is no sourceFileToPackageName anymore”). - The function always returns
false.
- The logic that would map declaration files to package names is commented out with a
-
typeDeclaredInDeclareModule(lines 210–217) only returns true when the type is declared inside an ambientdeclare module "package-name" { ... }block. Types that come from normal npm package.d.tsfiles (e.g.export interface ErrorLikein@apollo/client/core/types.d.ts) are not inside such a block, so they never match.
Result: for types from real npm packages, the package specifier path is never taken, so the allow list does not work for them.
Suggested fix
Implement (or re-enable) the mapping from declaration files to package names so that typeDeclaredInDeclarationFile can return true when the type’s declaration file belongs to the requested package (e.g. when the file is under node_modules/@apollo/client/ for package: "@apollo/client"). Alternatively, document that package specifiers are only supported for declare module-style declarations until this is implemented.
References
- Rule implementation:
internal/rules/only_throw_error/only_throw_error.go(usesutils.TypeMatchesSomeSpecifier(t, opts.Allow, ctx.Program)). - Specifier matching:
internal/utils/type_matches_specifier.go(typeMatchesSpecifier,typeDeclaredInPackageDeclarationFile,typeDeclaredInDeclarationFile,typeDeclaredInDeclareModule). - Related discussion: Issue #425 (proposal to remove
allow; this issue shows it is currently broken for package specifiers rather than merely “rarely used”).