🛁

namespaceを使って、コンポーネントのインポートを整理する

2024/07/23に公開

はじめに

Typescript の独自構文、namespaceはご存知でしょうか?
https://www.typescriptlang.org/docs/handbook/namespaces.html

過去に.を使って関数コンポーネントの型であるReact.FCを参照する機会あるかと思います。
ドット記法をで型を参照するのはnamespaceの機能です。

一般的なやり方

以下は一般的なやり方かと思います。

src/components/button.tsx
import * as React from "react";

export type ButtonProps = {
    label: string;
    onClick: () => void;
    variant?: "primary" | "secondary";
    size?: "small" | "medium" | "large";
 };

export default function Button(props: ButtonProps) { ... }

参照したい側でインポートする

src/App.tsx
import { Button, type ButtonProps } from "./components/button"; // 👈 コンポーネントとその型を参照する

export default function App() {
  const handleClick: ButtonProps["onClick"] = () => {
    console.log("clicked");
  };

  return (
    <div className='App'>
      <Button
        label='Click me'
        onClick={handleClick}
      />
    </div>
  );
}

この書き方では、コンポーネントとその型を同時にインポートを行なっています。
コンポーネントとその型の命名は重複不可であり、ButtonPropsInputProps、なんとか~Propsのような命名をせざるを得ないです。

整理する

namespaceの機能を使って、モジュールのインポートを整理しましょう。

src/components/button.tsx
import * as React from "react";

export namespace Button { // 👈 namespaceの宣言
  export type Props = {
    label: string;
    onClick: () => void;
  };
}

export function Button(props: Button.Props) { // 👈 namespaceの呼び出し
  return <button onClick={props.onClick}>{props.label}</button>;
}

button.tsxのコンポーネントの参照先のインポートを整理しましょう。

src/App.tsx
import { Button } from "./components/button"; // 👈 コンポーネント定義のみをインポートする

export default function App() {
  const handleClick: Button.Props["onClick"] = () => { // 👈 namespaceの呼び出し
    console.log("clicked");
  };
  return (
    <div className='App'>
      <Button
        label='Click me'
        onClick={handleClick}
      />
    </div>
  );
}

namespaceの中に、複数のtype を定義することもできます。

src/components/button.tsx
export namespace Button {
  export type Variants = "primary" | "secondary";
  export type Sizes = "small" | "medium" | "large";
  export type Props = {
    label: string;
    onClick: () => void;
    variant?: Variants;
    size?: Sizes;
  };
}

普段 namespace を使う機会ないと思いますので、ぜひ試してみてください!

GitHubで編集を提案

Discussion