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

[api-extractor] Support docs/trimming for members of a literal union type alias #4699

Open
AJIXuMuK opened this issue May 13, 2024 · 1 comment
Labels
effort: medium Needs a somewhat experienced developer enhancement The issue is asking for a new feature or design change

Comments

@AJIXuMuK
Copy link

Summary

Release tags (@alpha, @beta, @internal, @public) are great and allow having flexibility in API releases.
One of the features we would benefit from is the ability to specify the release tags for union types members.

Details

For example, we may have an existing API like

/**
  * @public
  */
export type IconSize = 'small' | 'medium';

We want to test a new large size as beta.
So we would like to be able to do something like:

/**
  * @public
  */
export type IconSize = 
| 'small' 
| 'medium' 
/**
 * @beta
 */
| 'large';

and allow API Extractor to create different definitions for public and beta releases.

This behavior can be "opt-in" only: for example, we may need to specify extra tsdoc tag to the type to process the type in a new way:

/**
  * @public
  * @formedType
  */
export type IconSize = 
| 'small' 
| 'medium' 
/**
 * @beta
 */
| 'large';

The same is applicable for union of interface:

/**
  * @public
  * @formedType
  */
export type ButtonType = 
| IPrimaryButton 
| ISecondaryButton
/**
 * @beta
 */
| IOutlineButton;

Standard questions

Please answer these questions to help us investigate your issue more quickly:

Question Answer
@microsoft/api-extractor version? latest
Operating system? any
API Extractor scenario? rollups (.d.ts) -->
Would you consider contributing a PR? maybe
TypeScript compiler version? 5.3.3
Node.js version (node -v)? 18.20.2
@octogonz octogonz changed the title [api-extractor]: ability to apply release tags to union types members separately. [api-extractor] Provide a way to document and trim members of a literal union type alias May 13, 2024
@octogonz
Copy link
Collaborator

This feature request is closely related to #3002 which asks for documenting/trimming members of a type alias that mimics an interface.

In general, type can produce arbitrarily complex expressions that are difficult for API Extractor to model as "API items" the documentation website, and are not safe for .d.ts trimming. (Specifically, the concern is that trimming members may produce .d.ts rollups that fail to compile, and it can be difficult to detect or correct such cases, due to the expressiveness/flexibility of the type system.)

But in both cases, type is being used for a restricted pattern that is very similar to an already supported API item kind:

#4699 involves a type that looks like ApiEnum:

/**
 * The icon size.
 * @public
 */
export type IconSize = 
  /** 
   * 16x16 pixels
   */
  'small' |
  /** 
   * 32x32  pixels
   * @beta
   */
  'medium';

#3002 involves a type that looks like ApiInterface:

export type Book = {
  /** The title */
  title: string;
  /** The description */
  description: string;
};

Thus, these particular patterns should be relatively well-behaved and straightforward to incorporate into the API item model. We could try to automatically detect them, but I think this would give a confusing experience. A seemingly small modification such as export type IconSize = 'small' | 'medium' | UnsupportedThing could suddenly cause the API docs for 'small' and 'medium' to disappear from the website, because the expected pattern is no longer matched.

Proposed design

Let's call the above patterns formed types which means a type that follows a predefined stereotypical form. The first example is a formed enum, and the second example is a formed interface, and in the future we could support more such patterns.

In this proposal, the user must declare the form explicitly, using new TSDoc tags such as @formedEnum or @formedInterface. For example:

/**
 * The icon size.
 * @formedEnum
 * @public
 */
export type IconSize = 
  /** 16x16 pixels */
  'small' |
  /** 32x32  pixels */
  'medium';

/**
 * @formedInterface
 * @public
 */
export type Book = {
  /** The title */
  title: string;
  /** The description */
  description: string;
};

With these tags, API Extractor will validate that the type conforms to the supported structure, and report an error message if not. And then members such as 'small' or title will become ApiItem objects in the model, with full support for .d.ts trimming and structured website documentation, just like ApiEnumMember or ApiProperty.

Whereas if you omit the @formedEnum and @formedInterface tags, then these declarations would instead become an ApiTypeAlias whose members are just a blob of text in the signature without any special interpretation.

Implementation

The @formedEnum and @formedInterface features involve considerations and algorithms, so let's continue to track them using separate GitHub issues.

This issue #4699 I think is the easier one to start with. We've already confirmed that the TypeScript compiler correctly propagates all the /** */ comments to the .d.ts file. One slightly tricky aspect is the position of |, for example...

export type IconSize = 
  /** 16x16 pixels */
  'small' |
  /** 32x32  pixels */
  'medium';

...versus...

export type IconSize = 
  /** 16x16 pixels */
  'small' 
  /** 32x32  pixels */
  | 'medium';

...and what would we do with...

export type IconSize = 
  /** 16x16 pixels */
  'small' 
  /** A */
  | 
  /** B */
  'medium';

We also need to decide whether to reuse ApiEnum and ApiEnumMember, or else define new model classes such as ApiFormedEnum and ApiFormedEnumMember. I don't have a strong opinion about this.

@octogonz octogonz added enhancement The issue is asking for a new feature or design change effort: medium Needs a somewhat experienced developer labels May 13, 2024
@octogonz octogonz changed the title [api-extractor] Provide a way to document and trim members of a literal union type alias [api-extractor] Support docs/trimming for members of a literal union type alias May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort: medium Needs a somewhat experienced developer enhancement The issue is asking for a new feature or design change
Projects
Status: Needs triage
Development

No branches or pull requests

2 participants