React、Next.jsにJSDocでコメントアウトを書こう！（TypeScript, Javascript）

# はじめに

突然ですが、ReactやNext.jsを書いている時、このようなコメントを見かけてこれなんやねん、と思った経験はないでしょうか？

```tsx
export interface ButtonOwnProps {
  /**
   * The content of the component.
   */
  children?: React.ReactNode;
  /**
   * Override or extend the styles applied to the component.
   */
  classes?: Partial<ButtonClasses>;
  /**
   * The color of the component.
   * It supports both default and custom theme colors, which can be added as shown in the
   * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
   * @default 'primary'
   */
  color?: OverridableStringUnion<
    'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning',
    ButtonPropsColorOverrides
  >;
  .......
}
```

これはMUIのButtonコンポーネントからの抜粋です。
ライブラリを使ったことがある方なら一回はこんな感じのコメントを見たことあるんじゃないかなと思います。

これはJSDocと言われる記法で書かれたコメントで、この記法を使ってコメントアウトを作成するとコードの可読性と保守性を向上させることができます。

## JSDoc(TSDoc)とは？

JSDocは、JavaScriptコードにコメントとして記述するドキュメンテーションフォーマットで、関数、変数、クラス、引数などの説明を追加することができます。JSDocコメントは、`/**`で始まり、特定のタグを用いてコードの説明を書きます。多くのエディタ（例えばVSCodeなど）がJSDocに対応しており、コメントを元にコードの補完機能やドキュメント生成が可能です。

## JSDocの基本的な書き方

jsonplaceholderのAPIを叩いてpostのtitleとbodyを表示するだけのコンポーネントにJSDoc形式のコメントを作成してみます。
コメントを書かない場合以下のようになります。

試してみたいけど環境ないよって方は以下を参考にNext.jsの環境を作成してください！
https://yasdtech.com/blog/i10869kx7tv

```page.tsx

"use client"
import Post from "@/app/components/Post";

export default function Home() {

  return (
    <Post title={"post"} />
  );
}
```


```Post.tsx
'use client'
import { useEffect, useState } from 'react'

export interface Post {
  userId: number
  id: number
  title: string
  body: string
}

type Props = {
  title: string
}

export default function Post(props: Props): JSX.Element {
  const [posts, setPosts] = useState<Post[]>([])

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/posts')
      const data = await response.json()
      setPosts(data)
    }

    fetchData()
  }, [])

  return (
    <div>
      <h1>{props.title}</h1>
      <ul>
        {posts.map((post: Post) => (
          <li key={post.id}>
            <h2>{post.title}</h2>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  )
}

```

よく見るNext.jsのコードだと思います。
このコンポーネントに対してJSDocでコメントを書くと以下のようになります。

```Post.tsx
"use client";
import { useEffect, useState } from "react";

/**
 * 投稿のレスポンス
 */
export interface Post {
  /**
   * 投稿を作成したユーザーのID
   */
  userId: number;

  /**
   * 投稿の一意なID
   */
  id: number;

  /**
   * 投稿のタイトル
   */
  title: string;

  /**
   * 投稿のボディ
   */
  body: string;
}

/**
 * props
 */
type Props = {
  /**
   * コンポーネントのタイトル
   */
  title: string;
};


/**
 * 投稿一覧のコンポーネント
 * @param props propsです
 * @returns {JSX.Element} 投稿一覧のJSX要素
 */
export default function Post(props: Props): JSX.Element {
  const [posts, setPosts] = useState<Post[]>([]);

  useEffect(() => {
  
    /**
     * jsonplaceholderからデータをfetchする
     * @returns {Promise<Post[]>} 投稿の一覧を含むPromise
     */
    const fetchData = async () => {
      const response = await fetch(
        "https://jsonplaceholder.typicode.com/posts"
      );
      const data = await response.json();
      setPosts(data);
    };

    fetchData();
  }, []);

  return (
    <div>
      <h1>{props.title}</h1>
      <ul>
        {posts.map((post: Post) => (
          <li key={post.id}>
            <h2>{post.title}</h2>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

```
まずこのコメントをどこに書くか、という話ですが基本的には関数と型定義のプロパティにコメントを割り振っていきます。
関数やプロパティの型定義の上に/**から始まるコメントを書くことで、エディタがその関数や型のコメントであると認識してくれるため、呼び出し側でホバーすると関数・型のコメントを確認することができます。

まずは型定義についてみてみましょう。
```typescript
interface Post {
  /**
   * 投稿を作成したユーザーのID
   */
  userId: number;

  /**
   * 投稿の一意なID
   */
  id: number;

  /**
   * 投稿のタイトル
   */
  title: string;

  /**
   * 投稿のボディ
   */
  body: string;
}
```
各プロパティに対してコメントを作成し、これをpostsのuseStateに当てはめていきます。
こうすることで{post.title}にホバーすると以下のように投稿のタイトルというコメントが表示されるようになります。

![スクリーンショット 2024-11-10 13.19.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3338449/86d40d86-8be8-9929-1b06-a99b7e56525d.png)


fetchData関数についてもみてみましょう。

```tsx
/**
 * jsonplaceholderからデータをfetchする
 * @returns {Promise<Post[]>} 投稿の一覧を含むPromise
 */
 const fetchData = async () => {
   const response = await fetch(
     "https://jsonplaceholder.typicode.com/posts"
   );
   const data = await response.json();
   setPosts(data);
 };

  fetchData();
  ```
fetchDataという関数にコメントアウトを作成しています。
この状態でfetchDataの呼び出し箇所にホバーすると画像のようになります。
@returnsというのはJSDocが提供する標準タグで、@タグ名　{返ってくる値のデータ型}　コメント
のように書きます。

![スクリーンショット 2024-11-10 13.35.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3338449/a6dd4d2f-ff8c-d07b-f28c-2f99f93fb970.png)

最後にコンポーネントです
コンポーネントの上に以下のようなコメントを書きます
```tsx
/**
 * 投稿一覧のコンポーネント
 * @param props propsです
 * @returns {JSX.Element} 投稿一覧のJSX要素
 */
export default function Post(props: Props): JSX.Element {
  const [posts, setPosts] = useState<Post[]>([]);
  .....
}
```
@paramも@returnsと同様、JSDocが提供する標準タグで、@タグ名 パラメータの名前　コメント
のように書きます。
この例ではpropsを取っているのでpropsのコメントを書いています。
この状態で、コンポーネントの呼び出し箇所にホバーすると以下のようになります。

![スクリーンショット 2024-11-10 13.43.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3338449/5387ba5a-4c05-51b3-de75-d80170caaa80.png)


## よく使うJSDocタグ
JSDocが標準で用意しているタグは色々ありますが、よく使うものとしていくつか挙げておきます。

- `@param`：関数の引数の説明に使います
- `@returns`：関数の戻り値を書く時に使います
- `@default`：デフォルト値がある場合に使います
- `@example`: 使用例を書く時に使います
- `@see`: 関連するドキュメント、参考情報のリンクを書く時に使います
- `@type`: 型情報を書く時に使います

他にも色々あるのでぜひみてみてください！
https://jsdoc.app/

## まとめ

JSDocを使うことで、JavaScriptやTypeScriptのコードに詳細なドキュメントを追加し、保守性と可読性を向上させることができます。特にReact、Next.jsに入門しただけの方は知らないことも多いと思うので参考になれば幸いです！