12

I'm trying to JSDoc a simple React Typescript component with hooks. Unfortunately, I can't seem to find a way that makes JSDoc work with declared destructured arrays. There are some answers related to destructuring object params, but these don't work for arrays.

/**
 * @property {boolean} 0 - documentation for isLoading
 * @property {func} 1 - documentation for setIsLoading
 */
 const [isLoading, setIsLoading] = React.useState<boolean>(false);

Update 1: Still having trouble finding a way to document this destructure. There is a corner case where if I custom type an object, it works:

export type AuthFormInput = {
  /** Value of the Email input field */
  email: string;
  /** Value of the Password input field */
  password: string;
};

const [form, setForm] = React.useState<AuthFormInput>({
  email: '',
  password: ''
});

...

// JSDoc will work here
const email = form.email;
shinglesmingles
  • 490
  • 3
  • 6
  • 14

4 Answers4

28

It would help:

    /**
     * @typedef {Boolean} LoadingState — documentation for isLoading
     * @description Additional doc
     */
    /**
     * @typedef {Function} LoadingStateSetter — documentation for setIsLoading
     */
    /**
     * @type {[LoadingState, LoadingStateSetter]} Loading
     */
    const [isLoading, setIsLoading] = React.useState();

In this example we declare two additional types: LoadingState and LoadingStateSetter. Then we add some description for them and finally, we declare the Loading type for the result of React.useState()

You also can declare it in a more simple way like this:

    /**
      * @type {[Boolean, Function]} Loading
      */
    const [isLoading, setIsLoading] = React.useState();

But I didn't find a way to add a description in this case.

I've checked the description of such way of documentation in VSCode

Nik
  • 2,170
  • 1
  • 14
  • 20
7

You can try this:

/** @type {boolean} */
const initialState = false
const [isLoading, setIsLoading] = React.useState(initialState)
Community
  • 1
  • 1
Yang Liu
  • 101
  • 1
  • 2
  • this is better because typescript would infer the type of isLoading and setIsLoading by itself +1. setIsLoading is more complex than `Function`, it is `React.Dispatch>` – Daniel Pérez Jan 28 '21 at 23:54
  • Note that this only work if there is one type that the variable can hold - meaning that if you wanted a nullable value for example, it will infer only a partial type (even if you specific the type for the variable). Kind of annoying to be honest... – Moshe Jonathan Gordon Radian Sep 24 '21 at 08:38
6

The actual best solution to be found here is by using parentheses. Otherwise jsdoc does not seem to catch it:

const [authFormInput, setAuthFormInput] = useState(/** @type {AuthFormInput} */({..}));
androidavid
  • 1,258
  • 1
  • 11
  • 20
0

The cleanest way I found is to use types.d.ts, since we're likely gonna need to type out more than just a useState and we can keep a lot of the code there for cleanliness:

// types.d.ts:
declare type State = string;
declare type SetState = (stateParam: State) => void;
declare type UseState = [State, SetState];

// component.jsx:
  /**
   * @type {UseState}
  */
  const [state, setstate] = useState("");