Rush StackShopBlogEvents
Skip to main content

ae-incompatible-release-tags

"The symbol is marked as , but its signature references which is marked as ."

Remarks

The TSDoc "release tags" form an ordering according to their visibility:

@public > @beta > @alpha > @internal

For example, when .d.ts trimming is applied, a "beta" release will include declarations marked as @public or @beta, but will omit declarations marked as @alpha or @internal. This prevents the developer from accidentally using an @alpha or @internal declaration.

But suppose we have an API like this:

/**
* Not visible in a "beta" release.
* @alpha
*/
export ICalculateOptions {
numerator: number;
denominator: number;
}

/**
* Visible in a "beta" release.
* @beta
*/
export function calculate(options: ICalculateOptions): void { // <-- problem!
}

// Warning: The symbol "calculate" is marked as "@beta", but its signature references
// "ICalculateOpations" which is marked as "@alpha"

When a developer is using the "beta" release, they won't be able to access the ICalculateOptions type needed to call the calculate() function. That's not good!

Similarly, suppose that a @beta class were to inherit from an @alpha class:

/**
* Not visible in a "beta" release.
* @alpha
*/
export class Control {
public constructor(x: height, y: width) {}
}

/**
* Visible in a "beta" release.
* @beta
*/
export class Button extends Control {
// <-- problem!
}

// Warning: "The symbol "Button" is marked as "@beta", but its signature references
// "Control" which is marked as "@alpha"

When a developer is using the "beta" release, they should not be using the Control type because it is marked as @alpha. But then how are they supposed to construct an instance of Button class, which relies on it?

It's interesting to consider what happens when the tags are reversed:

/**
* Visible in a "beta" release.
* @beta
*/
export class Control {
public constructor(x: height, y: width) {}
}

/**
* Not visible in a "beta" release.
* @alpha
*/
export class Button extends Control {
// <-- okay
}

In this example, the "beta" release hides the Button class, but it's still perfectly valid for a developer to use the base class Control. So there is no incompatibility here.

In general, the principle here is that a type signature should not reference another types whose release tag is less visible. API Extractor checks this for you, and will report ae-incompatible-release-tags if it detects an inconsistency.

How to fix

Correct the release tags so that the relationships are consistent.

See also