🛁
namespaceを使って、コンポーネントのインポートを整理する
はじめに
Typescript の独自構文、namespace
はご存知でしょうか?
過去に.
を使って関数コンポーネントの型である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>
);
}
この書き方では、コンポーネントとその型を同時にインポートを行なっています。
コンポーネントとその型の命名は重複不可であり、ButtonProps
やInputProps
、なんとか~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 を使う機会ないと思いますので、ぜひ試してみてください!
Discussion