Skip to main content

underscore-internal

Disallow @internal APIs that are not underscore-prefixed.

Targeted pattern scopeโ€‹

This rule checks identifier names for declarations/signatures such as:

  • class/function/type/interface/enum declarations,
  • variable declarators,
  • class methods/properties,
  • interface method/property signatures,
  • enum members.

It reports names that do not start with _ when @internal is present in a leading comment for the node (or its export declaration wrapper).

What this rule reportsโ€‹

This rule reports declarations tagged with @internal when their names do not begin with _.

The convention makes internal-only APIs visually obvious and helps prevent accidental public use.

Why this rule existsโ€‹

It enforces a consistent signal that internal-only APIs are not part of the public contract.

โŒ Incorrectโ€‹

/** @internal */
export function parseSecret(): void {}
export interface Thing {
/** @internal */
compute(): number;
}

โœ… Correctโ€‹

/** @internal */
export function _parseSecret(): void {}
export interface Thing {
/** @internal */
_compute(): number;
}

Behavior and migration notesโ€‹

This rule reports only and does not provide an autofix.

Migration is typically renaming internal declarations to use an underscore prefix.

Optionsโ€‹

This rule has no options.

Additional examplesโ€‹

/** @internal */
export const token = "x";
// โŒ reported

/** @internal */
export const _token = "x";
// โœ… valid

ESLint flat config exampleโ€‹

import etcMisc from "eslint-plugin-etc-misc";

export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/underscore-internal": "error",
},
},
];

When not to use itโ€‹

Disable this rule if your project uses a different naming convention for internal APIs.

Package documentationโ€‹

Rule catalog ID: R076

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.