Creating comprehensive and elaborate intellisense documentation for Typescript Union Types

When we call the baz function with the code provided, the typeahead will display 'a' and 'b' as potential values.

https://i.stack.imgur.com/SrKo7.png

If additional documentation is needed for each of these values, how can it be accomplished? For example, if the desired outcome is:

https://i.stack.imgur.com/Bbipq.png

To provide more context on the intention and purpose, let's consider the following example:

const paintColor = {
  /** This color is good fo X */
  Waltz: "#d9e5d7",
  /** This color is good fo Y */
  "Indiana Clay": "#ed7c4b",
  /** This color is good fo Z */
  Odyssey: "#575b6a"
};

const locations = {
  /** There are no good school at this location*/
  City: "123 city center road",
  /** There are lots of parking at this location but it is very far*/
  West: "245 some other road"
};

interface HouseProp {
  color: keyof typeof paintColor; //"Waltz" | "Indiana Clay" | "Odyssey"
  location: keyof typeof locations; //"City" | "West"
}

const House = ({ color, location }: HouseProp) => {
  ...
};

A react component called House renders a house based on the color and location props.

This House component is utilized extensively across the project.

Despite the current configuration, using House like this does not reflect the documented details in IntelliSense:

https://i.stack.imgur.com/ugG2L.png

The desired outcome would resemble this:

https://i.stack.imgur.com/4o4tt.png

Regarding the issue, while enums could be created for `paintColor` and `locations`, implementing them may not align with the original proposal.

import House, {HouseColor, HouseLocation} from './House';
<House color={HouseColor["Indiana Clay"]} location={HouseLocation.City} />

However, this approach lacks the elegance of the initial suggestion for the component interface.

Answer №1

When dealing with union members, annotating them can be a challenge. However, you can approach this issue in a different way by utilizing function overloads or opting for an enum instead.

Solution #1: Leveraging Function Overloads

/**
 * a is suitable for X
 */
function baz(param: 'a'): number;
/**
 * b is a great choice for Y
 */
function baz(param: 'b'): number;
function baz(param: 'a' | 'b'): number {
  return 1;
}

Screenshot

Solution #2: Using Overload as an Interface

interface Baz {
  /**
   * a is appropriate for X
   */
  (param: 'a'): number;
  /**
   * b is a fantastic choice for Y
   */
  (param: 'b'): number;
}

const baz: Baz = (param: 'a' | 'b') => {
  return 1;
}

Screenshot

Solution #3: Opting for an Enum Instead

enum Foo {
  /**
   * a is suitable for X
   */
  A = 'a',
  /**
   * b is a great choice for Y
   */
  B = 'b',
}

function baz(param: Foo) {
  return 1;
}

Screenshot

While this may not be the exact solution you were hoping for, it presents a viable alternative.

Answer №2

A current limitation in TypeScript involves handling string literals within union types, but it is unclear if this issue is being addressed. An example can be found in the TypeScript repository under issue ticket Support parsing TSDoc string comments #38106. Show your support for this ticket by giving it a thumbs up and subscribing to receive updates on its progress (while refraining from simple comments like "+1" or "me too").

Additionally, there are related issues in the TSDoc and typedoc repositories discussing similar topics: RFC: Specify that doc comments are allowed on simple union types #164 and Support for enum-like use of string literal types #1710.

If you require hover information for enumeration values, consider utilizing TypeScript's enum feature as a workaround, even though it may not be the desired solution. For instance:

/** FOO */
enum Foo {
   /** AAA */
   a = "a",
   /** BBB */
   b = "b",
   /** CCC */
   c = "c",
};
type FooArray = Foo[];

const foo = Foo.a;
const fooArray: FooArray = [Foo.a, Foo.b, Foo.c];

By hovering over the "a" in "Foo.a", you should see a tooltip displaying "AAA" for reference.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Uncover the content of a base64 encoded string and convert it into

A JSON response has been linked on the user's request to retrieve an excel document. The structure of the response is as follows: { "format": // file extn ----only xls "docTitle": //file name "document" :// base 64 encoded data } The attem ...

Warning: The attribute 'EyeDropper' is not recognized within the context of 'Window & typeof globalThis'

Attempting to utilize "window.EyeDropper" in a project that combines vue2 and TypeScript. When writing the following code: console.log(window.EyeDropper); An error message is generated by my Vetur plugin: Property 'EyeDropper' does not exist on ...

Is there a way to toggle the visibility of the angular material toolbar at regular intervals?

I'm currently experimenting with the CSS animation feature to display and conceal the angular material toolbar in this demonstration. Inside the application component, the hide attribute is toggled at intervals as shown below: hide:boolean = false ...

Applying TPS rate to existing API endpoints at the method level within API Gateway using AWS CDK

I have successfully set up a UsagePlan and connected it to an API stage with CDK. However, I am having difficulty implementing method throttling at the API stage for a specific resource path. Despite searching online, I have not been able to find a satis ...

"Facing an issue where ts-node is not recognizing d.ts files, despite tsc being able to compile them

I am currently using typescript along with express and attempting to enhance the request object in express. Below is my server.ts file: import express, { Request, Response } from "express"; const app = express(); app.use(function(req: Request, res: Respo ...

Angular fails to retrieve the data from an Object

I have both backend and frontend applications. When I attempt to retrieve information about the 'Probe' object, I can see its fields: https://i.stack.imgur.com/TJQqI.png However, when I try to access this information in Angular, I receive an und ...

Having trouble implementing object type switching in Typescript

While in the process of developing an angular application, I stumbled upon a peculiar issue. Some time ago, I crafted this piece of code which performed flawlessly: selectedGeoArea: any receiveStoreEvent(event) { switch (event.constructor) { ca ...

Explain the TypeScript type where the keys of an object not found in an array should correspond to the type of another object

Currently, I am developing a utility function called copyKnownProperties that is responsible for copying properties from one class or object to another only if the key exists on both objects. In the example provided, you can observe an attempt to copy prop ...

arrange elements by their relationship with parents and children using typescript and angular

Here is a list that needs to be sorted by parent and child relationships: 0: {id: 7, name: "333", code: "333", type: 3, hasParent: true, parentId: 4} 1: {id: 6, name: "dfgdfg", code: "dfgdfg", type: 3, hasParent: false, parentId: null} 2: {id: 5, name: ...

Function exported as default in Typescript

My current version of TypeScript is 1.6.2 and we compile it to ECMA 5. I am a beginner in TypeScript, so please bear with me. These are the imported library typings. The contents of redux-thunk.d.ts: declare module "redux-thunk" { import { Middle ...

When employing GraphQL Apollo refetch with React, the update will extend to various other components as well

My current setup involves using react along with Apollo. I have implemented refetch in the ProgressBar component, which updates every 3 seconds. Interestingly, another component named MemoBox also utilizes refetch to update the screen at the same int ...

What is the best way to dynamically disable choices in mat-select depending on the option chosen?

I was recently working on a project that involved using mat-select elements. In this project, I encountered a specific requirement where I needed to achieve the following two tasks: When the 'all' option is selected in either of the mat-select e ...

The type 'TaskListProps[]' cannot be assigned to type 'TaskListProps'

I'm struggling with handling types in my TypeScript application, especially with the TaskListProps interface. export default interface TaskListProps { tasks: [ { list_id: string; title: string; description: string; status ...

Error in Typescript TS2322: Observable Type 'boolean | {}' - Using Angular 5 and Typescript 2.4.2

After upgrading from version 4 to 5, I'm puzzled by the plethora of TypeScript TS2322 errors I'm encountering. The migration involved setting up a new Angular project with the Angular CLI. Angular CLI: 1.5.5 Node: 8.9.1 OS: darwin x64 Angular: 5 ...

Integrating Constant Contact API into a Next.js application

I'm trying to integrate the Constant Contact API into my Next.js application. I've looked through the documentation, but it only provides examples for PHP and Java. How can I effectively use the authentication flow and create an app on the dashbo ...

The type '{}' does not contain a property named 'map'

Recently delving into TypeScript, and I'm curious about the process of typing an axios response when storing it in a state variable. I've initiated a basic API call from App.tsx, which returns the following object: {data: {…}, status: 200, s ...

Efficient ways to manage dropdown cells in ReactGrid

Is there a way to assign individual values to each select element in a cell? I am using ReactGrid with react version 16 There seems to be an issue with the onchange function, and I'm struggling to find help import * as React from "react"; ...

Angular array of considerable size

Dealing with a massive array of 30,000 items can be quite daunting, especially when it comes in as a stream using grpc-web. Currently, I'm fetching the data from grpc.client() and populating an array before displaying it using *ngFor. However, I' ...

How can Observables be designed to exhibit both synchronous and asynchronous behavior?

From: Understanding the Contrasts Between Promises and Observables In contrast, a Promise consistently operates asynchronously, while an Observable can function in synchronous or asynchronous manners. This presents the opportunity to manipulate code in ...

The type 'Promise<any>' cannot be assigned to the type 'Contact[]'

After exhausting all my resources on the internet and StackOverflow, I still couldn't find the right answer. This is my first project in Angular with MongoDB, but I keep encountering this error: "Type 'Promise' is not assignable to type &apo ...