13

Given the following code, when we call the baz function, the typeahead will show 'a' and 'b' as possible values.

enter image description here

However, if I want to provide additional documentation for each of those values, how would I do it? For example, if something like this is the desired behavior:

enter image description here

I thought I should give more context about what I'm trying to do and why:

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) => {
  ...
};

Where House is a react component that renders a house based on the color and location props.

And this House component is used everywhere throughout the project.

With the current setup, I could use House like this:

<House color="Indiana Clay" location="City" />

The problem is, the IntelliSense can't pick up on the docs I've written as part of the code:

enter image description here

What I would like is this: enter image description here

P.S. I know that I could turn paintColor and locations into enums, and use things like this:

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

But that component interface just isn't as nice as my original proposal.

1
  • 1
    You're creating a type composed of unions of strings. How do you expect to annotate each basic string in that union? The overload suggestion below is excellent. Commented Aug 2, 2020 at 10:45

2 Answers 2

4
+50

You can't really annotate union members. You can, however, express your union differently — by using overloads or by choosing to use an enum instead.

Solution #1: Function overloads

/**
 * a is good fo X
 */
function baz(param: 'a'): number;
/**
 * b is an excellent choice for Y
 */
function baz(param: 'b'): number;
function baz(param: 'a' | 'b'): number {
  return 1;
}

Screenshot

Solution #2: Overload as an interface

interface Baz {
  /**
   * a is good fo X
   */
  (param: 'a'): number;
  /**
   * b is an excellent choice for Y
   */
  (param: 'b'): number;
}

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

Screenshot

Solution #3: Using an enum instead

enum Foo {
  /**
   * a is good fo X
   */
  A = 'a',
  /**
   * b is an excellent choice for Y
   */
  B = 'b',
}

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

Screenshot

I know that's not exactly what you'd like, but that's your second best option.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your suggestions. Unfortunately they are not quite what I'm after. I've edited the original question to give more context on what I'm trying to do and why. Perhaps you've better ideas on how things could be done?
1

This is a current behavioural limitation of TypeScript (not sure if it is in the backlog). For example, see this issue ticket in the TypeScript repo, which is about string literals in union types: Support parsing TSDoc string comments #38106. Give that issue ticket a thumbs up and subscribe to it to get notifications about discussion and progress (but please avoid noisy comments like "+1" / "bump" / "me too").

See also this related issue ticket in the TSDoc repo: RFC: Specify that doc comments are allowed on simple union types #164, and this issue ticket in the typedoc repo: Support for enum-like use of string literal types #1710.

If you want hover info for the enumeration values, then you could workaround it by switching to using TypeScript's enum feature (which the asker of this question has specified that they don't want to do, but I find still worth mentioning). Ex.

/** 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];

Then when you hover your mouse over the "a" in "Foo.a", you'll get a hover widget appear with "AAA" in it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.