no-internal
Disallow usage of symbols tagged with @internal.
Targeted pattern scopeโ
โ ๏ธ This rule requires type information to run. Configure type-aware linting (parserOptions.project or projectService) before enabling it.
This rule inspects identifier usages and resolves each identifier to a TypeScript symbol.
If the resolved symbol has one or more @internal JSDoc tags, usage is
reported (unless ignored via configuration).
What this rule reportsโ
APIs marked as @internal are implementation details that can change without
notice. Referencing them from external call sites couples your code to unstable
contracts and makes upgrades risky.
This rule reports identifier usages whose resolved TypeScript symbol includes
one or more @internal tags.
Why this rule existsโ
It prevents accidental dependency on unstable internals that are intentionally outside a package's supported API surface.
โ Incorrectโ
/** @internal */
interface InternalType {
readonly value: number;
}
const item: InternalType = { value: 42 };
/** @internal Internal function details */
declare function internalFunction(): void;
internalFunction();
โ Correctโ
interface PublicType {
readonly value: number;
}
const item: PublicType = { value: 42 };
/** @internal */
interface InternalType {
readonly value: number;
}
// Declaration is allowed. Only usage is reported.
Behavior and migration notesโ
This rule reports only and does not provide an autofix.
It ignores declaration identifiers and import/export specifier identifiers, and focuses on usage sites resolved through TypeScript symbol information.
Optionsโ
type Options = [
{
ignored?: Record<string, "name" | "path">;
}?,
];
Default:
[{}];
Use ignored to suppress some internal symbols by regular-expression pattern:
"name": Match against the symbol name."path": Match against the symbol's fully-qualified declaration path.
If an ignored key is not a valid regular expression, the rule reports a
configuration error (invalidIgnorePattern) instead of silently ignoring it.
Example:
import etcMisc from "eslint-plugin-etc-misc";
export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/no-internal": [
"error",
{
ignored: {
"^ExperimentalInternalType$": "name",
"modules/internal": "path",
},
},
],
},
},
];
Additional examplesโ
/** @internal Internal helper */
export declare const __internalThing: string;
const value = __internalThing;
// โ reported
// config: { ignored: { "^__internalThing$": "name" } }
const ignoredValue = __internalThing;
// โ
ignored by configuration
ESLint flat config exampleโ
import etcMisc from "eslint-plugin-etc-misc";
export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/no-internal": "error",
},
},
];
When not to use itโ
Disable this rule if your project intentionally consumes internal contracts and accepts the maintenance risk from those unstable dependencies.
Package documentationโ
Rule catalog ID: R028
Further readingโ
Adoption resourcesโ
- Start at warning level in CI, then move to error after cleanup.
- Use focused codemods/autofix batches per package or directory.